Получение всех типов, которые реализуют интерфейс в .NET Core

c# .net reflection lambda .net-core

10476 просмотра

6 ответа

195 Репутация автора

Используя отражение, Как я могу получить все типы, которые реализуют некоторый определенный интерфейс в .NET Core ? Я заметил, что методы, используемые в .NET 4.6, больше не доступны.

Например, этот код не работает.

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

Выдает The name 'AppDomain' does not exist in the current contextошибку.

Автор: Mr. Robot Источник Размещён: 18.07.2016 06:10

Ответы (6)


2 плюса

187112 Репутация автора

Насколько я могу судить, в .Net Core 1.0 невозможно получить все загруженные сборки. Кажется, способ сделать это запланировано на 1.1.

Автор: svick Размещён: 18.07.2016 07:46

16 плюса

176 Репутация автора

Решение

Вы можете сделать это так:

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

Если вы хотите, чтобы типы были во всех сборках, просто используйте следующее, чтобы получить все ссылки и повторите вышеописанное :)

ass.GetReferencedAssemblies()
Автор: littlewang Размещён: 03.03.2017 08:49

0 плюса

11 Репутация автора

Если вы хотите, чтобы типы были во всех сборках, просто используйте следующее, чтобы получить все ссылки и повторите вышеописанное :)

ass.GetReferencedAssemblies()
Автор: littlewang Размещён: 03.03.2017 09:09

0 плюса

239 Репутация автора

Возможное решение - сообщить интерфейсу, кто является объектами, которые его реализуют, [ServiceKnownTypeAttribute]и когда вам нужно знать типы, которые реализуют, получают по рефлексии. Пример:

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

И вы можете восстановить типы, которые реализованы с:

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;
    }
Автор: miguel Размещён: 03.03.2017 11:11

5 плюса

83 Репутация автора

Полный код, чтобы получить все классы, которые реализуют тип '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);
            }
        }
    }            
}
Автор: Edmilson Lani Размещён: 28.07.2017 09:03

7 плюса

940 Репутация автора

В .NET Core 2.0 вы можете найти все совпадающие типы в сборках, которые были известны во время компиляции (это не работает для динамически загружаемых сборок), например так:

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

Это зависит от пакета Microsoft.Extensions.DependencyModel .

Автор: Dave S Размещён: 20.09.2017 08:05
32x32