2009-02-06 10 views
31

¿Cómo probaría una propiedad de un tipo para ver si es un tipo especificado?¿Cómo puedo determinar los tipos de propiedad usando reflexión?

EDITAR: Mi objetivo es examinar un conjunto para ver si alguno de los tipos en ese conjunto contiene propiedades que son MyType (o heredadas de MyType).

Aquí está la pista que me he ido hacia abajo ...

AssemblyName n = new AssemblyName(); 
n.CodeBase = "file://" + dllName; 
Assembly a = AppDomain.CurrentDomain.Load(n); 

foreach (Type t in a.GetTypes()) 
    foreach (PropertyInfo pi in t.GetProperties()) 
     if (pi.PropertyType is MyType) // warning CS0184 
      Console.WriteLine("Found a property that is MyType"); 

Esto compila con la advertencia CS0184: La expresión dada nunca es proporcionado de la ('MyType') tipo

Respuesta

54

Qué tipo son te interesa? El tipo de devolución del método/propiedad/evento, etc.

Si es así, no creo que haya nada en MemberInfo dejar que podemos encontrar en ella directamente - se necesita para emitir y utilizar MethodInfo.ReturnType, PropertyInfo.PropertyType, FieldInfo.FieldType, EventInfo.EventHandlerType y cualesquiera otros que he olvidado. (Recuerde que los tipos mismos pueden ser miembros No está seguro de lo que usted querrá hacer con ellos.!)

EDIT: Si está interesado en saber si un tipo específico representa bien MyType o alguna subclase, a continuación, utilizar Type.IsAssignableFrom:

if (typeof(MyType).IsAssignableFrom(type)) 

EDITAR: Ahora que sabemos que desea propiedades, es fácil: utilice GetProperties en lugar de GetMembers. Me gusta hacer la reflexión con LINQ:

var query = from type in assembly.GetTypes() 
      from property in type.GetProperties() 
      where typeof(MyType).IsAssignableFrom(property.PropertyType) 
      select new { Type=type, Property=property }; 

foreach (var entry in query) 
{ 
    Console.WriteLine(entry); 
} 

Si no eres un fan de LINQ:

foreach (Type t in a.GetTypes()) 
    foreach (PropertyInfo pi in t.GetProperties()) 
     if (typeof(MyType).IsAssignableFrom(pi.PropertyType)) 
      Console.WriteLine("Found a property that is MyType"); 

Tenga en cuenta que es posible que desee especificar banderas de unión para obtener propiedades no públicos, etc.

+0

que debería haber dicho "propiedades" en vez de "miembros". He actualizado la pregunta, con suerte ahora está más clara. –

+0

@Jon Skeet: no relacionado: ¿has visto el anuncio FinalBuilder? ¡Bastante gracioso! –

+1

@Mitch: Sí. Me preguntaron muy bien si también estaba bien primero. –

1

Creo que se necesita algo como esto:

using System; 
using System.Reflection; 

namespace ConsoleApplication1{ 
    class Class1{ 

     static bool checkType(Type propertyType,Type myType){ 
      if (propertyType == myType){ 
       return true; 
      } 
      Type test = propertyType.BaseType; 
      while (test != typeof(Object)){ 
       if (test == myType){ 
        return true; 
       } 
       test = test.BaseType; 
      } 
      return false; 
     } 

     [STAThread] 
     static void Main(string[] args){ 
      Assembly a = Assembly.GetExecutingAssembly(); 
      foreach (Type t in a.GetTypes()){ 
       Console.WriteLine("Type: {0}",t.Name); 
       foreach (PropertyInfo p in t.GetProperties()){ 
        if (checkType(p.PropertyType,typeof(MyType))){ 
         Console.WriteLine(" Property: {0}, {1}",p.Name,p.PropertyType.Name); 
        } 
       } 
      } 
     } 
    } 

    class MyType{ 
    } 

    class MyType2 : MyType{ 
    } 

    class TestType 
    { 
     public MyType mt{ 
      get{return _mt;} 
      set{_mt = value;} 
     } 
     private MyType _mt; 
     public MyType2 mt2 
     { 
      get{return _mt2;} 
      set{_mt2 = value;} 
     } 
     private MyType2 _mt2; 
    } 
} 
+0

La advertencia que recibo es CS0184: La expresión dada nunca es del tipo proporcionado –

+0

Eso es porque su tipo es System.Type ... verifique mi código, espero que ayude. –

1

que buscas:

if (typeof(mi) is MyType) { ... } 

derecho?

+0

Esto no funcionará, ya que el tipo de typeof (mi) es Type, no MyType – HAL9000

1

Existen múltiples maneras de probar un tipo de objeto:

1) utilizar el es operador:

if (anObject is MyType) { 
// anObject is MyType or a derived class 
... 
} 

2) Usar la como operador:

MyType newObject = anObject as MyType; 
if (newObject != null) { 
// newObject is anObject cast to MyType 
... 
} 

3) Utilice typeof() y GetType() [3 variaciones]:

// #1 
if (typeof(MyType) == anObject.GetType()) { 
// anObject is a MyType 
... 
} 

//#2 
public static bool IsType(object obj, string type) 
{// modified from Visual C# 2005 Recipes {Apress} 
// Get the named type, use case-insensitive search, throw 
// an exception if the type is not found. 
Type t = Type.GetType(type, true, true); 
return t == obj.GetType(); 
} 

//#3 
public static bool IsTypeOrSubclass(object obj, string type) 
{// modified from Visual C# 2005 Recipes {Apress} 
// Get the named type, use case-insensitive search, throw 
// an exception if the type is not found. 
Type t = Type.GetType(type, true, true); 
return t == obj.GetType() || obj.GetType().IsSubclassOf(t); 
} 
43

Ok, tal vez estoy perdiendo algo estúpido, pero no debería ser:

if (pi.PropertyType == typeof(MyType)) 

???

+0

Spot on, gracias por agregar esto. –

+0

¡Gracias por esta solución! – grmbl

+1

Y si su tipo es genérico (por ejemplo, DbSet <>) puede intentar esto ... if (pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof (DbSet <>)) { ... } – timothy

0

Este ejemplo de la otra pregunta similar simplificar el entendimiento para mí una gran cantidad

If p.PropertyType Is GetType(String) Then

0

que puedes usar is al comparar una instancia de algo con un tipo explícitamente escrito:

Department sales = new Department("Sales"); 

Debug.Assert(sales is Department); 

Debe usar typeof cuando desee comparar 2 tipos y no puede escribir el tipo explícitamente:

private void CheckType(Type t) 
{ 
    Debug.Assert(typeof(Department) == t); 
} 

El uso de is tendrá en cuenta la herencia, typeof no.

public class Animal { } 
public class Dog : Animal { } 

public void Test() 
{ 
    Dog d = new Dog(); 

    Debug.Assert(d is Animal); // true 

    Debug.Assert(typeof(Dog) == typeof(Animal); // false 
} 

Si desea comparar 2 tipos y tomar inheritence en cuenta, puede utilizar IsAssignableFrom:

Debug.Assert(typeof(Animal).IsAssignableFrom(typeof(Dog))); // true 
0

Esta es la forma de acceso directo

property.PropertyType.IsGenericType && (typeof(ICollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition())) 
&& typeof(<YourType>).IsAssignableFrom(property.PropertyType.GenericTypeArguments[0]) 
Cuestiones relacionadas