Получение всех типов, реализующих интерфейс в .NET Core
Использование отражения Как я могу получить все типы, которые реализуют определенный интерфейс в .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
.
Ответы
Ответ 1
вы можете сделать так:
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()
Ответ 2
Насколько я могу судить, нет способа получить все загруженные сборки в .Net Core 1.0. Кажется, способ сделать это запланирован на 1.1.
Ответ 3
Полный код, чтобы получить все.
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);
}
}
}
}
Ответ 4
В .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.
Ответ 5
Если вам нужны типы во всех сборках, просто используйте следующее, чтобы получить все ссылки и повторите следующее:)
ass.GetReferencedAssemblies()
Ответ 6
Возможное решение - сказать интерфейсу, которые являются объектами, которые реализуют его с помощью [ServiceKnownTypeAttribute]
, и когда вам нужно знать типы, которые реализуют get by reflexion. Пример:
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;
}