2011-12-27 18 views

cevap

42

Bu, genel bir temel sınıfını devralan tüm türleri döndürecektir. Genel bir arabirimi devralan her tür değil.

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; 

Bu arayüzler, özet ve bunun miras zincirinde açık genel türü var beton türleri de dahil her türlü, dönecektir.

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; 
} 

Bu ikinci yöntem bu örnekte ConcreteUserRepo ve IUserRepository bulacaksınız: Sen deneyebilirsiniz

public interface ConcreteUserRepo : IUserRepository 
{} 

public interface IUserRepository : IRepository<User> 
{} 

public interface IRepository<User> 
{} 

public class User 
{} 
+2

Evet, ancak aynı düzenekte olduğunda yalnızca concreterepo ve irepo elde edersiniz. Ama bu kesinlikle tamam. – Rookian

+0

İyi yakalama! Sadece yüklü olanları taramak yerine tüm bağımlı montajları yüklemeye özen göstermeliyiz. İşte tüm montajları yükleme hakkında bir SO: http://stackoverflow.com/questions/2384592/c-net-is-there-a-way-to-force-all-referenced-assemblies-to-be-loaded-into- –

+0

typeof (IRepository <>), yalnızca jenerik türün tek bir genel parametresi varsa çalışır. Birden fazla genel tür parametresi olan türler için herhangi bir fikir var mı? – dotnetguy

2

openGenericType.IsAssignableFrom(myType.GetGenericTypeDefinition()) 

veya

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

Çözüm, LINQ olmadan, genel ve genel olmayan arabirimleri ararken, dönüş türünü sınıflara göre filtreleyerek gerçekleştirilir.

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"; 
    } 
} 
İlgili konular