2010-09-02 15 views
5

Nota: questo è un follow-up di un answer su un previous question.Utilizzare la riflessione per ottenere l'attributo di una proprietà tramite il metodo chiamato dal setter

Sto decorando il setter di una proprietà con un attributo chiamato TestMaxStringLength utilizzato nel metodo chiamato dal setter per la convalida.

L'immobile attualmente si presenta così:

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

ma vorrei piuttosto simile a questa:

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

Il codice per ValidateProperty che è responsabile per la ricerca degli attributi del setter è :

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. 
} 

Come modificareCodiceper cercare gli attributi nella proprietà anziché set?

risposta

7

Per quanto ne so, non c'è modo di ottenere un PropertyInfo da un MethodInfo di uno dei suoi setter. Sebbene, naturalmente, potresti usare alcuni hack di stringhe, come usare il nome per la ricerca e così via. Sto pensando qualcosa come:

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

Inutile dire che, tuttavia, non è esattamente performante.

Inoltre, fai attenzione con la classe StackTrace - anche un maiale da prestazione, se usato troppo spesso.

2

Nella classe che dichiara il metodo, è possibile cercare la proprietà che contiene quel setter. Non è performante, ma nemmeno lo è 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

si potrebbe considerare, come un approccio alternativo, ritardando la convalida fino al più tardi, eliminando così la necessità di ispezionare la traccia dello stack.

Questo esempio fornisce un attributo ...

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

... a Poco con l'attributo applicato ad una struttura ...

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

... e uno stub classe di utilità che convalida l'oggetto.

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. Mi piace molto questo approccio da una prospettiva di codifica. Ovviamente, la decorazione degli attributi è inutile a meno che non venga implementata la validazione, il che è un po 'più difficile da assumere in questo modello, ma nel complesso dovrebbe essere più veloce e più pulito. –

+0

potresti dirmi come convalidare il valore rispetto a atts? Grazie! – VladL

Problemi correlati