web-dev-qa-db-fra.com

Obtenir tous les types qui implémentent une interface dans .NET Core

En utilisant la réflexion, comment puis-je obtenir tous les types qui implémentent une interface spécifique dans .NET Core ? J'ai remarqué que les méthodes utilisables dans .NET 4.6 ne sont plus disponibles.

Par exemple, ce code ne fonctionne pas.

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

Il jette l'erreur The name 'AppDomain' does not exist in the current context.

10
Mr. Robot

vous pouvez faire de cette façon:

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

Si vous voulez des types dans tous les assemblys, utilisez simplement ce qui suit pour obtenir toutes les références et répétez l'opération ci-dessus :)

ass.GetReferencedAssemblies()
13
littlewang

Dans .NET Core 2.0, vous pouvez trouver tous les types correspondants dans des assemblys connus au moment de la compilation (cela ne fonctionne pas pour les assemblys chargés de manière dynamique), comme ceci:

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

Cela dépend du Microsoft.Extensions.DependencyModel package.

6
Dave S

Le code complet pour obtenir toutes les classes qui implémentent le type 'T'

public static IEnumerable<T> GetAll<T>()
{
    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);
            }
        }
    }            
}
5
Edmilson Lani

Autant que je sache, il n’existe aucun moyen d’obtenir tous les assemblys chargés dans .Net Core 1.0. Il semble qu'un moyen de faire cela est prévu pour 1.1.

2
svick

Si vous voulez des types dans tous les assemblys, utilisez simplement ce qui suit pour obtenir toutes les références et répétez l'opération ci-dessus :)

ass.GetReferencedAssemblies()
0
littlewang

Une solution possible est d'indiquer à l'interface quels sont les objets qui l'implémentent avec [ServiceKnownTypeAttribute] et quand vous avez besoin de connaître les types qui implémentent get par réflexion. Exemple:

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

Et vous pouvez récupérer les types implémentés avec: 

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