Domanda

I need to explain a bit to get to the problem.

I have 3 projects:

Project 1 can see project 2 and 3.

Project 2 can see project 3.

Project 3 is a dll and the others are apps.

I had to design a class with a lot of subclasses. The subclasses all have a method which is declared as abstract in the base, so they all have to use it. They need to get distributed in all projects, because the code in methode directly interacts with the project.

The abstract base classes are in Project 3, the subclasses are in 2 and 1. There's the problem I have:

This is the method I wrote:

   public static IEnumerable<Type> GetSubClasses(Type typ)
   {
       IEnumerable<Type> subclasses =
       from type in Assembly.GetAssembly(typ).GetTypes()
       where type.IsSubclassOf(typ) && !type.IsAbstract
       select type;
       return subclasses;
   }

I'm trying to get all subclasses of the type but when I do, I only get the subclasses from the current project. For example, if I try to get them from project1, I dont get the subclasses from project 2.

How do I do that? I know I can get an assembly reference from project 2 but it has no GetAssembly(Type t) method, with the help of that I'm getting all the subclasses. If it would be the same I just had to do the same there.

My second question is, is there an easier way at all? It's a bit.."large" having those classes in many projects, maybe there's a solution to get them into one. Like I said, the code of the methode they all need to have, needs to directly interact with the project they are in.

È stato utile?

Soluzione

The problem is you're calling Assembly.GetTypes(). That gives you only the classes in that particualr assembly. If you have Assembly objects for all three assemblies, you can do something like

assem1.GetTypes()
.Concat(assem2.GetTypes())
.Concat(assem3.GetTypes())

So the problem is how you get the three Assembly objects. From project 1 you can just say

var assem1 = typeof(SomeClassInProj1).Assembly;
var assem2 = typeof(SomeClassInProj2).Assembly;
var assem3 = typeof(SomeClassInProj3).Assembly;

In a project where you can't "see" the other assemblies, you need to load them. See the documentation of Assembly.Load.

Altri suggerimenti

Any base class, or interface should not know or care about its inheritors or implmenters. Any interaction should be limited to abstract or virtual members that are overridden.

Likewise, an assembly that exports public types is not designed to know anything about the importers. Doing so with "Early Binding" would create a circular reference.

You could concieveably reflect all assemblies loaded into your application domain and see which inherit from a certain type but, what do you intend to do with this information? There is probably a simpler, faster way of achieveing that.

You have to load all assemblies which might contain types you want to find and look for the types like you do in a loop.

I have done something like that for get a list of all classes from assemblies in the current applications bin folder, that inherit from some base class:

// load all files from current dir which ends with `.dll`
var q = from s in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll")
        select s;

var types = q.Select(s => getTypes(s, myBaseType))
             .SelectMany(typeList => typeList).ToList();

And the function getTypes:

IEnumerable<Type> getTypes(string filePath, Type baseType) {
    Assembly a = Assembly.LoadFrom(filePath);
    return a.GetTypes().Where(t => t.IsSubclassOf(baseType) && !t.IsAbstract);
}

You have to deal with some exceptions like BadImageFormatException when you have dll in your folder which are not .net assemblies.

Another approach might be to configure the list of assemblies you want to inspect.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top