2010-09-02 17 views
5

Nota: Esto es una continuación de answer en un previous question.Utilice la reflexión para obtener el atributo de una propiedad a través del método llamado desde el colocador

estoy decorando seleccionador de propiedades con un atributo llamado TestMaxStringLength que se utiliza en el método llamado de la incubadora para su validación.

La propiedad actualmente tiene el siguiente aspecto:

public string CompanyName 
{ 
    get 
    { 
     return this._CompanyName; 
    } 
    [TestMaxStringLength(50)] 
    set 
    { 
     this.ValidateProperty(value); 
     this._CompanyName = value; 
    } 
} 

pero preferiría que tener este aspecto:

[TestMaxStringLength(50)] 
public string CompanyName 
{ 
    get 
    { 
     return this._CompanyName; 
    } 
    set 
    { 
     this.ValidateProperty(value); 
     this._CompanyName = value; 
    } 
} 

El código para ValidateProperty que se encarga de buscar los atributos del colocador es :

private void ValidateProperty(string value) 
{ 
    var attributes = 
     new StackTrace() 
      .GetFrame(1) 
      .GetMethod() 
      .GetCustomAttributes(typeof(TestMaxStringLength), true); 
    //Use the attributes to check the length, throw an exception, etc. 
} 

¿Cómo puedo cambiar elCódigopara buscar atributos en la propiedad en lugar del conjunto método?

Respuesta

7

Hasta donde yo sé, no hay forma de obtener un PropertyInfo de un MethodInfo de uno de sus instaladores. Aunque, por supuesto, podrías usar algunos hacks de cuerdas, como usar el nombre para la búsqueda, y tal. Estoy pensando algo como:

var method = new StackTrace().GetFrame(1).GetMethod(); 
var propName = method.Name.Remove(0, 4); // remove get_/set_ 
var property = method.DeclaringType.GetProperty(propName); 
var attribs = property.GetCustomAttributes(typeof(TestMaxStringLength), true); 

No hace falta decirlo, sin embargo, eso no es exactamente perfecto.

Además, tenga cuidado con la clase StackTrace; también es muy útil cuando se usa con demasiada frecuencia.

2

En la clase que declara el método, puede buscar la propiedad que contiene ese setter. No es efectivo, pero tampoco lo es StackTrace.

void ValidateProperty(string value) 
{ 
    var setter = (new StackTrace()).GetFrame(1).GetMethod(); 

    var property = 
     setter.DeclaringType 
       .GetProperties() 
       .FirstOrDefault(p => p.GetSetMethod() == setter); 

    Debug.Assert(property != null); 

    var attributes = property.GetCustomAttributes(typeof(TestMaxStringLengthAttribute), true); 

    //Use the attributes to check the length, throw an exception, etc. 
} 
2

Podría considerar, como un enfoque alternativo, retrasar la validación hasta más tarde, eliminando así la necesidad de inspeccionar el seguimiento de la pila.

Este ejemplo proporciona un atributo ...

public class MaxStringLengthAttribute : Attribute 
{ 
    public int MaxLength { get; set; } 
    public MaxStringLengthAttribute(int length) { this.MaxLength = length; } 
} 

... a poco con el atributo aplicado a una propiedad ...

public class MyObject 
{ 
    [MaxStringLength(50)] 
    public string CompanyName { get; set; } 
} 

... y un talón de clase de utilidad que valida el objeto

public class PocoValidator 
{ 
    public static bool ValidateProperties<TValue>(TValue value) 
    { 
     var type = typeof(TValue); 
     var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); 
     foreach (var prop in props) 
     { 
      var atts = prop.GetCustomAttributes(typeof(MaxStringLengthAttribute), true); 
      var propvalue = prop.GetValue(value, null); 

      // With the atts in hand, validate the propvalue ... 
      // Return false if validation fails. 
     } 

     return true; 
    } 
} 
+0

Ooh. Me gusta mucho este enfoque desde una perspectiva de codificación. Por supuesto, la decoración del atributo es inútil a menos que se implemente la validación, que es un poco más difícil de asumir en este modelo, pero en general debería ser más rápido y más limpio. –

+0

¿podría decirme cómo validar el valor contra atts? ¡Gracias! – VladL

Cuestiones relacionadas