2011-12-27 24 views

Trả lời

42

Điều này sẽ trả về tất cả các loại kế thừa một lớp cơ sở chung. Không phải tất cả các loại thừa hưởng giao diện chung.

var AllTypesOfIRepository = from x in Assembly.GetAssembly(typeof(AnyTypeInTargetAssembly)).GetTypes() 
let y = x.BaseType 
where !x.IsAbstract && !x.IsInterface && 
y != null && y.IsGenericType && 
y.GetGenericTypeDefinition() == typeof(IRepository<>) 
select x; 

Điều này sẽ trả về tất cả các loại, bao gồm giao diện, tóm tắt và loại bê tông có loại mở chung trong chuỗi kế thừa của nó.

public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly) 
{ 
    return from x in assembly.GetTypes() 
      from z in x.GetInterfaces() 
      let y = x.BaseType 
      where 
      (y != null && y.IsGenericType && 
      openGenericType.IsAssignableFrom(y.GetGenericTypeDefinition())) || 
      (z.IsGenericType && 
      openGenericType.IsAssignableFrom(z.GetGenericTypeDefinition())) 
      select x; 
} 

Phương pháp thứ hai này sẽ tìm ConcreteUserRepoIUserRepository trong ví dụ này:

public interface ConcreteUserRepo : IUserRepository 
{} 

public interface IUserRepository : IRepository<User> 
{} 

public interface IRepository<User> 
{} 

public class User 
{} 
+2

Có, nhưng bạn sẽ chỉ nhận được concreterepo và irepo khi nó ở trong cùng một cụm. Nhưng điều này là hoàn toàn ok. – Rookian

+0

Tốt bắt! Chúng tôi phải cẩn thận để tải tất cả các hội đồng phụ thuộc, không chỉ quét hiện đang được nạp. Đây là một SO về tải tất cả các hội đồng: http://stackoverflow.com/questions/2384592/c-net-is-there-a-way-to-force-all-referenced-assemblies-to-be-loaded-into- –

+0

Loại (IRepository <>) chỉ hoạt động nếu loại chung có một tham số chung duy nhất. Bất kỳ ý tưởng nào cho các loại có nhiều thông số loại chung? – dotnetguy

2

Bạn có thể thử

openGenericType.IsAssignableFrom(myType.GetGenericTypeDefinition()) 

hoặc

myType.GetInterfaces().Any(i => i.Type == openGenericType) 
3

Giải pháp được triển khai không có LINQ, tìm kiếm cả giao diện chung và không chung chung, lọc kiểu trả về thành các lớp.

public static class SampleCode 
{ 
    public static void Main() 
    { 
     IList<Type> loadableTypes; 

     // instance the dummy class used to find the current assembly 
     DummyClass dc = new DummyClass(); 

     loadableTypes = GetClassesImplementingAnInterface(dc.GetType().Assembly, typeof(IMsgXX)).Item2; 
     foreach (var item in loadableTypes) {Console.WriteLine("1: " + item);} 
     // print 
     // 1: Start2.MessageHandlerXY 

     loadableTypes = GetClassesImplementingAnInterface(dc.GetType().Assembly, typeof(IHandleMessageG<>)).Item2; 
     foreach (var item in loadableTypes) { Console.WriteLine("2: " + item); } 
     // print 
     // 2: Start2.MessageHandlerXY 
     // 2: Start2.MessageHandlerZZ 
    } 

    ///<summary>Read all classes in an assembly that implement an interface (generic, or not generic)</summary> 
    // 
    // some references 
    // return all types implementing an interface 
    // http://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface/12602220#12602220 
    // http://haacked.com/archive/2012/07/23/get-all-types-in-an-assembly.aspx/ 
    // http://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes 
    // return all types implementing a generic interface 
    // http://stackoverflow.com/questions/33694960/find-all-types-implementing-a-certain-generic-interface-with-specific-t-type 
    // http://stackoverflow.com/questions/8645430/get-all-types-implementing-specific-open-generic-type 
    // http://stackoverflow.com/questions/1121834/finding-out-if-a-type-implements-a-generic-interface 
    // http://stackoverflow.com/questions/5849210/net-getting-all-implementations-of-a-generic-interface 
    public static Tuple<bool, IList<Type>> GetClassesImplementingAnInterface(Assembly assemblyToScan, Type implementedInterface) 
    { 
     if (assemblyToScan == null) 
      return Tuple.Create(false, (IList<Type>)null); 

     if (implementedInterface == null || !implementedInterface.IsInterface) 
      return Tuple.Create(false, (IList<Type>)null); 

     IEnumerable<Type> typesInTheAssembly; 

     try 
     { 
      typesInTheAssembly = assemblyToScan.GetTypes(); 
     } 
     catch (ReflectionTypeLoadException e) 
     { 
      typesInTheAssembly = e.Types.Where(t => t != null); 
     } 

     IList<Type> classesImplementingInterface = new List<Type>(); 

     // if the interface is a generic interface 
     if (implementedInterface.IsGenericType) 
     { 
      foreach (var typeInTheAssembly in typesInTheAssembly) 
      { 
       if (typeInTheAssembly.IsClass) 
       { 
        var typeInterfaces = typeInTheAssembly.GetInterfaces(); 
        foreach (var typeInterface in typeInterfaces) 
        { 
         if (typeInterface.IsGenericType) 
         { 
          var typeGenericInterface = typeInterface.GetGenericTypeDefinition(); 
          var implementedGenericInterface = implementedInterface.GetGenericTypeDefinition(); 

          if (typeGenericInterface == implementedGenericInterface) 
          { 
           classesImplementingInterface.Add(typeInTheAssembly); 
          } 
         } 
        } 
       } 
      } 
     } 
     else 
     { 
      foreach (var typeInTheAssembly in typesInTheAssembly) 
      { 
       if (typeInTheAssembly.IsClass) 
       { 
        // if the interface is a non-generic interface 
        if (implementedInterface.IsAssignableFrom(typeInTheAssembly)) 
        { 
         classesImplementingInterface.Add(typeInTheAssembly); 
        } 
       } 
      } 
     } 
     return Tuple.Create(true, classesImplementingInterface); 
    } 
} 

public class DummyClass 
{ 
} 

public interface IHandleMessageG<T> 
{ 
} 

public interface IHandleMessage 
{ 
} 

public interface IMsgXX 
{ 
} 

public interface IMsgXY 
{ 
} 

public interface IMsgZZ 
{ 
} 

public class MessageHandlerXY : IHandleMessageG<IMsgXY>, IHandleMessage, IMsgXX 
{ 
    public string Handle(string a) 
    { 
     return "aaa"; 
    } 
} 

public class MessageHandlerZZ : IHandleMessageG<IMsgZZ>, IHandleMessage 
{ 
    public string Handle(string a) 
    { 
     return "bbb"; 
    } 
} 
Các vấn đề liên quan