Реализации интерфейса через Reflection
Как я могу получить все реализации интерфейса через отражение в C#?
6 ответов
Ответ таков; он просматривает весь домен приложения, то есть каждую сборку, загруженную в настоящее время вашим приложением.
/// <summary>
/// Returns all types in the current AppDomain implementing the interface or inheriting the type.
/// </summary>
public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
return AppDomain
.CurrentDomain
.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => desiredType.IsAssignableFrom(type));
}
Это используется как это;
var disposableTypes = TypesImplementingInterface(typeof(IDisposable));
Вы также можете захотеть, чтобы эта функция находила реальные конкретные типы - то есть, отфильтровывая рефераты, интерфейсы и определения общих типов.
public static bool IsRealClass(Type testType)
{
return testType.IsAbstract == false
&& testType.IsGenericTypeDefinition == false
&& testType.IsInterface == false;
}
Посмотри на Assembly.GetTypes()
метод. Он возвращает все типы, которые можно найти в сборке. Все, что вам нужно сделать, это перебрать каждый возвращаемый тип и проверить, реализует ли он необходимый интерфейс.
Один из способов сделать это использует Type.IsAssignableFrom
метод.
Вот пример. myInterface
это интерфейс, реализации которого вы ищете.
Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
if (myInterface.IsAssignableFrom(type))
Console.WriteLine(type.FullName);
}
Я верю, что это не очень эффективный способ решить вашу проблему, но, по крайней мере, это хорошее место для начала.
Assembly assembly = Assembly.GetExecutingAssembly();
List<Type> types = assembly.GetTypes();
List<Type> childTypes = new List<Type>();
foreach (Type type in Types) {
foreach (Type interfaceType in type.GetInterfaces()) {
if (interfaceType.Equals(typeof([yourinterfacetype)) {
childTypes.Add(type)
break;
}
}
}
Может быть, что-то подобное....
Вот некоторые Type
методы расширения, которые могут быть полезны для этого, как предложил Simon Farrow. Этот код является просто реструктуризацией принятого ответа.
Код
/// <summary>
/// Returns all types in <paramref name="assembliesToSearch"/> that directly or indirectly implement or inherit from the given type.
/// </summary>
public static IEnumerable<Type> GetImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
var typesInAssemblies = assembliesToSearch.SelectMany(assembly => assembly.GetTypes());
return typesInAssemblies.Where(abstractType.IsAssignableFrom);
}
/// <summary>
/// Returns the results of <see cref="GetImplementors"/> that match <see cref="IsInstantiable"/>.
/// </summary>
public static IEnumerable<Type> GetInstantiableImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
var implementors = abstractType.GetImplementors(assembliesToSearch);
return implementors.Where(IsInstantiable);
}
/// <summary>
/// Determines whether <paramref name="type"/> is a concrete, non-open-generic type.
/// </summary>
public static bool IsInstantiable(this Type type)
{
return !(type.IsAbstract || type.IsGenericTypeDefinition || type.IsInterface);
}
Примеры
Чтобы получить реализуемые экземпляры в вызывающей сборке:
var callingAssembly = Assembly.GetCallingAssembly();
var httpModules = typeof(IHttpModule).GetInstantiableImplementors(callingAssembly);
Чтобы получить разработчиков в текущем домене приложений:
var appDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var httpModules = typeof(IHttpModule).GetImplementors(appDomainAssemblies);
Вы должны перебрать все интересующие вас сборки. Из сборки вы можете получить все типы, которые она определяет. Обратите внимание, что когда вы делаете AppDomain.CurrentDomain.Assemblies, вы получаете только загруженные сборки. Сборки не загружаются до тех пор, пока они не потребуются, что означает, что вам необходимо явно загрузить сборки перед началом поиска.
Вы имеете в виду все интерфейсы, которые реализует Type?
Как это:
ObjX foo = new ObjX();
Type tFoo = foo.GetType();
Type[] tFooInterfaces = tFoo.GetInterfaces();
foreach(Type tInterface in tFooInterfaces)
{
// do something with it
}
Надеюсь, что поможет.