2011-02-10 23 views

Respuesta

705

Usted tiene algunas opciones de la parte superior de mi cabeza

  1. typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

  2. typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

+55

Recuerde que typeof (IMyInterface) .IsAssignableFrom (typeof (IMyInterface)) también es verdadero, lo que puede tener un resultado inesperado en su código. –

+21

Seguro que fue fácil no prestar atención y obtener los argumentos para 'IsAssignableFrom' al revés. Iré con 'GetInterfaces' ahora: p – Benjamin

+10

La variante' IsAssignableFrom (t1) 'es aproximadamente 3 veces más rápida que la contraparte' GetInterfaces(). Contains (t2) 'en mi código. –

25
typeof(IMyInterface).IsAssignableFrom(someclass.GetType()); 

o

typeof(IMyInterface).IsAssignableFrom(typeof(MyType)); 
+24

Si ya tiene una instancia de la clase un enfoque mucho mejor es simplemente 'someclass es IMyInterface' como que no implica el costo de la reflexión en absoluto.Entonces, aunque no está mal, no es una forma ideal de hacerlo. –

+1

@James - De acuerdo. Incluso Resharper da la misma sugerencia. –

+0

@ JamesJ.ReganIV deberías publicar eso como una respuesta, casi me perdí tu comentario – reggaeguitar

10
public static bool ImplementsInterface(this Type type, Type ifaceType) { 
     Type[] intf = type.GetInterfaces(); 
     for (int i = 0; i < intf.Length; i++) { 
      if (intf[ i ] == ifaceType) { 
       return true; 
      } 
     } 
     return false; 
    } 

Creo que esta es la versión correcta, por tres razones:

1) Utiliza GetInterfaces y no IsAssignableFrom, es más rápido ya que IsAssignableFrom finalmente después de varias comprobaciones llaman a GetInterfaces.
2) Se itera sobre la matriz local, por lo que no habrá límites de verificación.
3) Utiliza el operador == que se define para Tipo, por lo que probablemente sea más seguro que el método Equals (que la llamada Contiene, usará eventualmente).

+7

+1 por contenido, odio los espacios alrededor de los parens y los frenillos egipcios. También todo el método puede escribirse como: return type.GetInterfaces(). Any (t => t == ifaceType); – reggaeguitar

+0

Type.IsAssignableFrom() internaly actúa exactamente como su código – devi

+0

También por qué no escribe.GetInterfaces(). Contiene (ifaceType) que no utiliza LINQ. –

4

Como alguien ya mencionado: Benjamin Abr 10 '13 a las 22:21"

Seguro que era fácil no prestar atención y obtener los argumentos para IsAssignableFrom hacia atrás.Voy a ir con GetInterfaces ahora: p -

Bueno, otro revés es sólo para crear un método de extensión corta que cumple, en cierta medida, la forma "más habitual" de pensar (y de acuerdo este es un muy poca elección personal para que sea un poco "más natural", basada en las preferencias de uno):

public static class TypeHelpers 
{ 
    public static Boolean IsAssignableTo(Type type, Type assignableType) 
    { 
     return assignableType.IsAssignableFrom(type); 
    } 
} 

public static class TypeExtensions 
{ 
    public static Boolean IsAssignableTo(this Type type, Type assignableType) 
    { 
     return TypeHelpers.IsAssignableTo(type, assignableType); 
    } 
} 

Y por qué no va un poco más genérico (bueno, no estoy seguro si es realmente tan interesante, así que supongo que estoy solo pasando otra pizca de azúcar 'sintaxis'):

public static class TypeHelpers 
{ 
    public static Boolean IsAssignableTo(Type type, Type assignableType) 
    { 
     return assignableType.IsAssignableFrom(type); 
    } 

    public static Boolean IsAssignableTo<TAssignable>(Type type) 
    { 
     return TypeHelpers.IsAssignableTo(type, typeof(TAssignable)); 
    } 
} 

public static class TypeExtensions 
{ 
    public static Boolean IsAssignableTo(this Type type, Type assignableType) 
    { 
     return TypeHelpers.IsAssignableTo(type, assignableType); 
    } 

    public static Boolean IsAssignableTo<TAssignable>(this Type type) 
    { 
     return TypeHelpers.IsAssignableTo<TAssignable>(type); 
    } 
} 

yo creo que puede ser mucho más natural de esa manera, pero una vez más sólo una cuestión de opiniones muy personales:

var isTrue = michelleType.IsAssignableTo<IMaBelle>(); 
+3

¿Hay alguna razón por la que no haya puesto la implementación directamente en el método de extensión? Quiero decir que esto te permite llamarlo de ambas maneras, pero ¿por qué necesitarías hacer eso? – MarqueIV

5
respuesta de

Modificación de Jeff para un rendimiento óptimo (gracias a la prueba de rendimiento de Pierre Arnaud):

var type = typeof(MyType); 
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass; 

encontrar todo tipo que implementan una interfaz en un determinado Assembly:

var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes() 
          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass); 
0

lo Abou t

if(MyType as IMyInterface != null) 

?

+2

Esto es obvio cuando tengo una instancia. No es útil cuando tengo un Type from reflection – edc65

0

¿Qué hay de

typeof(IWhatever).GetTypeInfo().IsInterface 
3

que acabo de hacer:

public static bool Implements<I>(this Type source) where I : class 
{ 
    return typeof(I).IsAssignableFrom(source); 
} 

Me gustaría poder haber dicho where I : interface, pero interface no es una opción genérica parámetro de restricción. class está lo más cerca posible.

Uso:

if(MyType.Implements<IInitializable>()) 
    MyCollection.Initialize(); 

me acaba de decir Implements porque eso es más intuitivo. Siempre obtengo IsAssignableFrom flip-flopped.

0

IsAssignableFrom se mueve ahora a TypeInfo así que .... typeof (ISMSRequest) .GetTypeInfo(). IsAssignableFrom (typeof (T) .GetTypeInfo())

0

Una respuesta correcta es

typeof(MyType).GetInterface(nameof(IMyInterface)) != null; 

Sin embargo,

typeof(MyType).IsAssignableFrom(typeof(IMyInterface)); 

podría devolver un resultado incorrecto, ya que el código siguiente se muestra con una cuerda y IConvertible:

static void TestIConvertible() 
    { 
     string test = "test"; 
     Type stringType = typeof(string); // or test.GetType(); 

     bool isConvertibleDirect = test is IConvertible; 
     bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible)); 
     bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null; 

     Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}"); 
     Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}"); 
     Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}"); 
    } 

Resultados:

isConvertibleDirect: True 
isConvertibleTypeAssignable: False 
isConvertibleHasInterface: True 
+0

Como puede ver en la respuesta aceptada, intercambió los tipos en el uso de 'IsAssignableFrom'. Al igual que Benjamin y Ehouarn advierten sobre. – VV5198722

Cuestiones relacionadas