2016-07-18 162 views
10

Uso della riflessione, Come posso ottenere tutti i tipi che implementano un'interfaccia specifica in . NET Core? Ho notato che i metodi utilizzabili in .NET 4.6 non sono più disponibili.Come ottenere tutti i tipi che implementano un'interfaccia in .NET Core

Ad esempio, questo codice non funziona.

var type = typeof(IMyInterface); 
var types = AppDomain.CurrentDomain.GetAssemblies() 
    .SelectMany(s => s.GetTypes()) 
    .Where(p => type.IsAssignableFrom(p)); 

Si genera l'errore The name 'AppDomain' does not exist in the current context.

+2

Sono sicuro che il codice funziona correttamente, non si dispone di un 'AppDomain'. –

+0

@BlueEyedBehemoth quindi Come includere AppDomain? : D –

+0

Per cosa ti serve? Di solito non è qualcosa con cui scherzi. –

risposta

9

si può fare in questo modo:

System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly(); 

foreach (System.Reflection.TypeInfo ti in ass.DefinedTypes) 
{ 
    if (ti.ImplementedInterfaces.Contains(typeof(yourInterface))) 
    { 
     ass.CreateInstance(ti.FullName) as yourInterface; 
    } 
} 

Se volete tipi in tutte le assemblee, semplicemente utilizzare la seguente per avere tutti i riferimenti e fare di nuovo quanto sopra :)

ass.GetReferencedAssemblies() 
+0

Questo ottiene solo i tipi all'interno di un singolo assieme, non tutti gli assiemi caricati. –

+1

Stenografia con LINQ var types = Assembly.GetEntryAssembly(). DefinedTypes.Where (ti => ti.ImplementedInterfaces.Contains (typeof (ILogger))). Select (m => m.FullName); –

0

Se vuoi i tipi in tutti gli assembly, basta semplicemente utilizzare quanto segue per ottenere tutti i riferimenti e fare nuovamente quanto sopra :)

ass.GetReferencedAssemblies() 
0

Una possibile soluzione è indicare all'interfaccia chi sono gli oggetti che lo implementano con [ServiceKnownTypeAttribute] e quando è necessario conoscere i tipi che implementano ottengono dalla riflessione. Esempio:

public class TypeWithImplementOne : IMyInterface 
{ 
    public string Hi() 
    { 
    return "hi"; 
    } 

} 
public class TypeWithImplementTwo : IMyInterface 
{ 
    public string Hi() 
    { 
    return "hi"; 
    } 
} 
public interface IMyInterface{ 
{ 
    [ServiceKnownType(typeof(TypeWithImplementOne))] 
    [ServiceKnownType(typeof(TypeWithImplementTwo))] 

    string Hi(); 
} 

E si può recuperare i tipi che attuate con:

private IEnumerable<string> GetKnownTypes() 
    { 
     List<string> result = new List<string>(); 

     Type interfaceType = typeof(IMyInterface); 
     IEnumerable<CustomAttributeData> attributes = interfaceType.CustomAttributes 
      .Where(t => t.AttributeType == typeof(ServiceKnownTypeAttribute)); 

     foreach (CustomAttributeData attribute in attributes) 
     { 
      IEnumerable<CustomAttributeTypedArgument> knownTypes = attribute.ConstructorArguments; 
      foreach (CustomAttributeTypedArgument knownType in knownTypes) 
      { 
       result.Add(knownType.Value.ToString()); 
      } 
     } 

     result.Sort(); 
     return result; 
    } 
2

Il codice completo per ottenere tutti.

public static IEnumerable<T> GetAll() 
{ 
    var assembly = Assembly.GetEntryAssembly(); 
    var assemblies = assembly.GetReferencedAssemblies(); 

    foreach (var assemblyName in assemblies) 
    { 
     assembly = Assembly.Load(assemblyName); 

     foreach (var ti in assembly.DefinedTypes) 
     { 
      if (ti.ImplementedInterfaces.Contains(typeof(T))) 
      { 
       yield return (T)assembly.CreateInstance(ti.FullName); 
      } 
     } 
    }    
} 
1

In .NET core 2.0, è possibile trovare tutti i tipi di corrispondenza in assemblee che erano noti al momento della compilazione (questo non funziona per assembly caricati dinamicamente) come questo:

private static IEnumerable<Type> GetAllTypesOf<T>() 
{ 
    var platform = Environment.OSVersion.Platform.ToString(); 
    var runtimeAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(platform); 

    return runtimeAssemblyNames 
     .Select(Assembly.Load) 
     .SelectMany(a => a.ExportedTypes) 
     .Where(t => typeof(T).IsAssignableFrom(t)); 
} 

Questo si basa su il pacchetto Microsoft.Extensions.DependencyModel.