-1

I am developing C#/.NET 3.5 app (and would like to stay on that version of .NET), and can’t figure how to solve this problem using Reflection. I found workaround, but is not “neat”. Code as below, I need to discover all Interface implementations, so that in the future when adding more Interface implementations I do not need to change existing code.

interface Ii { }
class A : Ii { }
class A1 : A { }
class A2 : A { }
class A3 : A { }
class B : Ii { }
class C : Ii{ }
// maybe in future class D : Ii { }
// maybe in future class E : Ii { }

class Helper
{
    static List<Type> GetAllInterfaceImplemenations()
    {// do reflection magic and return ["A1","A2","A3","B","C"] ...
     // I will use this method to fill comboBox-es , create objects factory, etc...
     // there should be no changes if/when in future I add class D etc.
    }
}
Dan
  • 9,717
  • 4
  • 47
  • 65
Mark_55
  • 155
  • 1
  • 9
  • 1
    Since you want to work with the Types you shouldnt use ArrayList. Better use List – CSharpie Apr 10 '13 at 17:31
  • a similar question has been asked here, you can take a look at my answer there: http://stackoverflow.com/questions/13994579/how-can-i-use-reflection-or-alternative-to-create-function-calls-programatically/13994668#13994668 – user287107 Apr 10 '13 at 17:29

2 Answers2

5

Try this:

public static List<string> GetAllInterfaceImplemenations()
{
    var interfaceType = typeof(Ii);
    var list = new List<string>();
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        if (type.IsClass && interfaceType.IsAssignableFrom(type))
        {
            list.Add(type.Name);
        }
    }

    return list;
}
Dan
  • 9,717
  • 4
  • 47
  • 65
0

Problem with above solution is that it will return class “A” from example above, which is not wanted. Only “Leafs” are wanted. But, above solution gives idea how to solve it. So, here is my production solution (sorry guys, ArrayList is my favorite collection...).

private static ArrayList GetAllInterfaceImplemenations()
{
    ArrayList listOfLeafsNames = null;
    try
    {
        Type interfaceType = typeof(ISpeechCodec);
        ArrayList listOfAll = new ArrayList();
        foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
        {
            if (type.IsClass && interfaceType.IsAssignableFrom(type))
            {
                listOfAll.Add(type);
            }
        }

        listOfLeafsNames = new ArrayList();
        foreach (Type typeCandidate in listOfAll)
        {
            bool isLeaf = true;
            foreach (Type type2 in listOfAll)
            {
                if (!(typeCandidate.Equals(type2)))
                {
                    if (typeCandidate.IsAssignableFrom(type2))
                    {
                        isLeaf = false;
                    }
                }
            }
            if (isLeaf)
            {
                listOfLeafsNames.Add(typeCandidate.FullName);
            }
        }
    }
    catch (Exception ex)
    {
        Setup_TraceExceptions(ex.ToString());
    }

    return listOfLeafsNames;
}
Mark_55
  • 155
  • 1
  • 9
  • how about marking class A as abstract? that would be the clean way to distinguish between classes which should not be created and the ones which should – user287107 Apr 22 '13 at 06:33