Реализации интерфейса через Reflection - PullRequest
39 голосов
/ 17 сентября 2008

Как я могу получить все реализации интерфейса через отражение в C #?

Ответы [ 6 ]

58 голосов
/ 17 сентября 2008

Ответ таков; он просматривает весь домен приложения, то есть каждую сборку, загруженную в настоящее время вашим приложением.

/// <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;
}
5 голосов
/ 17 сентября 2008

Взгляните на Assembly.GetTypes() метод. Он возвращает все типы, которые можно найти в сборке. Все, что вам нужно сделать, это перебрать каждый возвращаемый тип и проверить, реализует ли он необходимый интерфейс.

Один из способов сделать это - использовать метод Type.IsAssignableFrom.

Вот пример. myInterface - это интерфейс, реализации которого вы ищете.

Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
    if (myInterface.IsAssignableFrom(type))
        Console.WriteLine(type.FullName);
}

Я верю, что это не очень эффективный способ решения вашей проблемы, но, по крайней мере, это хорошее место для начала.

4 голосов
/ 17 сентября 2008
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;
       }
  }
}

Может быть, что-то в этом роде ...

3 голосов
/ 24 июня 2013

Вот некоторые 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);
1 голос
/ 17 сентября 2008

Вы должны перебрать все интересующие вас сборки. Из сборки вы можете получить все типы, которые она определяет. Обратите внимание, что когда вы делаете AppDomain.CurrentDomain.Assemblies, вы получаете только загруженные сборки. Сборки не загружаются до тех пор, пока они не потребуются, что означает, что вам необходимо явно загрузить сборки перед началом поиска.

1 голос
/ 17 сентября 2008

Вы имеете в виду все интерфейсы, которые реализует Тип?

Как это:

ObjX foo = new ObjX();
Type tFoo = foo.GetType();
Type[] tFooInterfaces = tFoo.GetInterfaces();
foreach(Type tInterface in tFooInterfaces)
{
  // do something with it
}

Надеюсь, что поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...