2016-07-18 12 views
10

Verwenden von Reflektion, wie kann ich alle Typen erhalten, die eine bestimmte Schnittstelle in .NET Core implementieren? Ich habe festgestellt, dass die in .NET 4.6 verwendbaren Methoden nicht mehr verfügbar sind.Abrufen aller Typen, die eine Schnittstelle in .NET Core implementieren

Zum Beispiel funktioniert dieser Code nicht.

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

Es löst The name 'AppDomain' does not exist in the current context Fehler.

+2

Ich bin sicher, dass Code gut funktioniert, Sie haben einfach keine 'AppDomain'. –

+0

@BlueEyedBehemoth So Wie man AppDomain einbeziehen? : D –

+0

Wozu brauchst du es? Es ist normalerweise nicht etwas, womit du dich beschäftigst. –

Antwort

9

Sie auf diese Weise tun können:

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

Wenn Sie Typen in allen Baugruppen wollen, einfach nur die folgenden verwenden, um alle Referenzen zu bekommen und wieder die oben tun :)

ass.GetReferencedAssemblies() 
+0

Das ruft nur die Typen innerhalb einer einzelnen Assembly ab, nicht alle geladenen Assemblys. –

+1

Kurzschrift mit LINQ var types = Assembly.GetEntryAssembly(). DefinedTypes.Where (ti => ti.ImplementedInterfaces.Contains (typeof (ILogger))) .Wählen Sie (m => m.FullName); –

0

Wenn Sie Typen in allen Baugruppen möchten, verwenden Sie einfach die folgenden, um alle Referenzen zu erhalten und das obige erneut zu tun :)

ass.GetReferencedAssemblies() 
0

Eine mögliche Lösung ist zu sagen, Schnittstelle, die die Objekte sind, die es mit [ServiceKnownTypeAttribute] implementieren und wenn Sie die Typen wissen müssen, die durch Reflexion erhalten implementieren. Beispiel:

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

Und Sie können die Typen wiederherstellen, die mit umgesetzt:

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

Der vollständige Code alle zu bekommen.

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 können Sie alle passenden Typen in Baugruppen finden, die zum Zeitpunkt der Kompilierung bekannt waren (das funktioniert nicht für dynamisch beanspruchte Baugruppen) wie folgt aus:

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

Dies beruht auf das Microsoft.Extensions.DependencyModel Paket.