2009-04-29 15 views
15

puedo estar haciendo esta mal, pero puede/cómo se puede encontrar campos de una clase en sí mismo ... por ejemplo ...C# Reflexión: Finding atributos en un campo miembro

public class HtmlPart { 
    public void Render() { 
    //this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false); 
    } 
} 

public class HtmlForm { 
    private HtmlPart _FirstPart = new HtmlPart();  
    [Optional] //<-- how do I find that? 
    private HtmlPart _SecondPart = new HtmlPart(); 
} 

O tal vez Estoy haciendo esto incorrectamente ... ¿Cómo puedo llamar a un método y luego verificar los atributos aplicados a sí mismo?

Además, por el bien de la cuestión - Tengo curiosidad si era posible encontrar información de atributos sin saber/acceder a la clase padre!

Respuesta

12

Si entiendo bien su pregunta, creo que lo que estamos tratando de hacer no es posible ...

En el método Render, que desea obtener un atributo posible aplicado al objeto. El atributo pertenece al campo _SecondPart que pertenece a la clase HtmlForm.

Para que trabajar que tendría que pasar el objeto que llama al método Render:

public class HtmlPart { 
     public void Render(object obj) { 
      FieldInfo[] infos = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 

      foreach (var fi in infos) 
      { 
       if (fi.GetValue(obj) == this && fi.IsDefined(typeof(OptionalAttribute), true)) 
        Console.WriteLine("Optional is Defined"); 
      } 
     } 
    } 
+0

Gracias - Parecía 'posible', pero de nuevo me imaginé que faltaba lo suficiente como para no funcionar. – Hugoware

+2

No, el método Render puede acceder perfectamente a typeof (HtmlForm) en lugar de obj.GetType(), entonces ya no necesita el obj. Por supuesto, si HtmlForm en sí mismo era privado, entonces podría necesitar encontrarlo a través de Assembly.GetExecutingAssembly(). GetTypes(). Where (t =>! T.IsGeneric &&! T.IsNested && t.FullName == "MyNamespace. HtmlForm ") o algo así. – Timwi

5

puede encontrar campos de una clase con Type.GetFields, y se pueden encontrar atributos aplicados a un campo utilizando MemberInfo.GetCustomAttributes o IsDefined - pero si usted necesita para encontrar todos los campos de un tipo particular, vas a tener que :

  • iterar sobre todos los conjuntos que desee buscar
  • iterar sobre todos los tipos dentro de cada conjunto
  • iterar sobre todos los campos dentro de cada tipo
  • Comprobar si el atributo de presencia/ausencia para cada campo

Ahora, si usted está realmente tratando de averiguar "es un atributo particular aplicado a un campo cuyo valor es una referencia a 'este' objeto" entonces eso es aún más difícil, porque tendrías que saber todo sobre cada objeto en el sistema. También debe tener en cuenta que no puede haber dos campos tanto con el mismo valor, es decir, haciendo referencia al mismo objeto. ¿El objeto contará como "opcional" en ese caso o no?

Básicamente, si el objeto debe tener una propiedad (por ejemplo, opcionales o no), entonces ese debe ser una propiedad del objeto en sí mismo, no el campo que contiene la propiedad.

Podría ser que estoy malinterpretando lo que está tratando de hacer, pero I sospecha o bien no es posible o al menos no es una buena idea. ¿Podrías explicar la imagen más grande aquí? ¿Qué estás realmente tratando de lograr con este atributo?

+0

Gracias por la respuesta - En este momento es más un experimento que cualquier otra cosa. Me preguntaba si era posible, ya que era una forma peculiar de tratar de llegar a esa información. – Hugoware

10

He aquí un ejemplo de dado un solo objeto cómo encontrar si cualquiera de los campos públicos o privados sobre ese objeto tiene una propiedad específica:

var type = typeof(MyObject); 
foreach (var field in type.GetFields(BindingFlags.Public | 
      BindingFlags.NonPublic | BindingFlags.Instance)) 
{ 
    if (field.IsDefined(typeof(ObsoleteAttribute), true)) 
    { 
     Console.WriteLine(field.Name); 
    } 

} 

Para la segunda parte de su pregunta se puede comprobar si un atributo es defiend en el método actual usando:

MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute)); 

Editar

para responder a su edición sí i Es posible sin saber el tipo real. La siguiente función toma un parámetro de tipo y devuelve todos los campos que tienen un atributo dado. Alguien en algún lugar conocerá el Tipo que desea buscar o tendrá una instancia del tipo que desea buscar.

Sin que tendría que hacer como Jon Skeet dijo que es enumerar sobre todos los objetos en una asamblea.

public List<FieldInfo> FindFields(Type type, Type attribute) 
    { 
     var fields = new List<FieldInfo>(); 
     foreach (var field in type.GetFields(BindingFlags.Public | 
          BindingFlags.NonPublic | 
          BindingFlags.Instance)) 
     { 
      if (field.IsDefined(attribute, true)) 
      { 
       fields.Add(field); 
      } 

     } 
     return fields; 
    } 
Cuestiones relacionadas