简体   繁体   中英

Better Solution to find all classes which inherit from a baseclass (and interface) and return a list not List<System.Type> but List<Interface>

Maybe my brain is not working properly and i cant see the forest because of the trees ...

Currently I have a class called CheckManager which searches the current assembly for a certain type called UserControlBaseCheck which is declared in a separate library. (this works fine)

I do have a variable AllChecks of type SortedDictionary<IBaseCheck, UserControlBaseCheck> (and a custom IComparer class which know's how to sort IBaseCheck ).

This variable AllChecks is used to populate a Stack . The stack is then worked through by a User, once it is depleted, it get's filled again with new instances of all classes inside the AllChecks variable. And the whole game starts again.

Currently i solved it this way:

//declaration of my container with all checks
private static SortedDictionary<IBaseCheck, UserControlBaseCheck> AllChecks =
        new SortedDictionary<IBaseCheck, UserControlBaseCheck>(new Comparer());

// this is how i call the method to find all classes which inherit from the type
FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(UserControlBaseCheck));

//this is the definition... it seems to me bit odd that I have to use the Activator 
//and create an instance and cast it to the interface just to do 
//what i want to do... 
//is there any other / easier / better way of doing so?
public static IList<IBaseCheck> FindDerivedTypes(Assembly assembly,Type baseType)
{
      //FYI: until the '.Select' I get a list of type List<System.Type>
      List<IBaseCheck> o = assembly.GetTypes()
        .Where(t => t != baseType && baseType.IsAssignableFrom(t))
        .Select(type => Activator.CreateInstance(type) as IBaseCheck)
        .ToList();

      return o;
}

i find it odd that I have to create first an instance of the type just to use/convert it to an interface. Why can't i just do: .Select(x=> x as IBaseCheck) I mean i have already a list with object of type List<System.Type> and it seems to me bit overkill what i am doing just to get my list of type IBaseCheck ( List<IBaseCheck> )

Why can't I just do: .Select(x=> x as IBaseCheck)

Because x is an instance of the System.Type type, not your UserControlBaseCheck type.

It's important to understand that, when you use reflection, you are getting the metadata for the types. Ie you are getting data that describes your types, not the types themselves. The System.Type type is one such kind of data. It is a runtime object that describes the types you declare. It is not those actual types, and it's definitely not an instance of those types.

Consider the trivial code example:

namespace ExampleNamespace
{
    class A { }
}

There are many different ways of getting the System.Type that represents that type:

Type type1 = Assembly.GetType("ExampleNamespace.A"),
    type2 = typeof(A),
    type3 = (new A()).GetType();

But note that in the above, all three variables wind up with the same instance of System.Type . Ie the instance that describes that type A.

Note also in the last assignment, to the variable type3 , a new instance of A is being created. Ie you can ask an instance for the information about its own type. But what's returned is not, of course, that instance. It's something completely different: the instance of System.Type describing the type of that instance of A .


So back to your example… You're using reflection to search for instances of specific System.Type objects. These instances give you enough information to figure out which ones implement some base class (or even an interface, if you wanted). But since you want an actual instance of that class, you need to explicitly ask for one.

Just as you can't do this:

A a = typeof(A);

You also can't do this:

IBaseCheck baseCheck = typeof(UserControlBaseCheck);

Instead, you need to do this:

IBaseCheck baseCheck = new UserControlBaseCheck();

And the way that's done via reflection (well, one way anyway) is to call the Activator.CreateInstance() method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM