it-swarm-es.tech

Implementaciones de interfaz a través de Reflection

¿Cómo puedo obtener todas las implementaciones de una interfaz a través de la reflexión en C #?

39
Chethan

La respuesta es esta; busca en todo el dominio de la aplicación, es decir, en cada ensamblado cargado actualmente por su aplicación.

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

Se usa así;

var disposableTypes =  TypesImplementingInterface(typeof(IDisposable));

También es posible que desee que esta función encuentre tipos concretos reales, es decir, filtrar resúmenes, interfaces y definiciones de tipos genéricos.

public static bool IsRealClass(Type testType)
{
    return testType.IsAbstract == false
         && testType.IsGenericTypeDefinition == false
         && testType.IsInterface == false;
}
58
Steve Cooper

Eche un vistazo al método Assembly.GetTypes(). Devuelve todos los tipos que se pueden encontrar en un ensamblaje. Todo lo que tiene que hacer es recorrer cada tipo devuelto y verificar si implementa la interfaz necesaria.

Una de las formas de hacerlo es usando Type.IsAssignableFrom método.

Aquí está el ejemplo. myInterface es la interfaz, implementaciones que está buscando.

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

Creo que no es una forma muy eficiente de resolver su problema, pero al menos, es un buen lugar para comenzar.

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

Quizás algo así ...

4
Adam Driscoll

Aquí hay algunos métodos de extensión Type que pueden ser útiles para esto, como lo sugiere Simon Farrow . Este código es solo una reestructuración de la respuesta aceptada.

Código

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

Ejemplos

Para obtener los implementadores instanciables en la Asamblea de convocatoria:

var callingAssembly = Assembly.GetCallingAssembly();
var httpModules = typeof(IHttpModule).GetInstantiableImplementors(callingAssembly);

Para obtener los implementadores en el dominio de aplicación actual:

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

Debe recorrer todos los ensamblajes que le interesen. Desde el ensamblaje puede obtener todos los tipos que define. Tenga en cuenta que cuando hace AppDomain.CurrentDomain.Assemblies solo obtiene los ensamblados que se cargan. Los ensamblajes no se cargan hasta que se necesitan, por lo que significa que debe cargar explícitamente los ensamblajes antes de comenzar a buscar.

1
Hallgrim

¿Te refieres a todas las interfaces que implementa un tipo?

Me gusta esto:

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

Espero que ayude.

1
Alex Duggleby