Подтвердить что ты не робот

Реализация интерфейса через Reflection

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

На этом пути используется метод Type.IsAssignableFrom.

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

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

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

Ответ 3

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

Может быть, что-то подобное....

Ответ 4

Вот некоторые Type методы расширения, которые могут быть полезны для этого, как предложено Саймон Фарроу. Этот код является просто реструктуризацией принятого ответа.

Код

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

Чтобы получить реализации в текущем AppDomain:

var appDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var httpModules = typeof(IHttpModule).GetImplementors(appDomainAssemblies);

Ответ 5

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

Вот так:

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

Надеюсь, что у тебя есть.

Ответ 6

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