2010-09-02 55 views
5

注意:這是對previous question上的answer的後續操作。使用反射通過從設置者調用的方法獲取屬性的屬性

我正在用一個名爲TestMaxStringLength的屬性裝飾一個屬性的setter,該屬性在setter調用的方法中用於驗證。

該物業目前看起來是這樣的:

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

但我寧願它是這樣的:

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

ValidateProperty的代碼,負責查找的屬性設置器:

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

如何更改ValidateProperty代碼尋找屬性屬性而不是設置方法

回答

7

據我所知,沒有辦法從其setter的MethodInfo中獲取PropertyInfo。雖然,當然,你可以使用一些字符串黑客,比如使用查找名稱等。我在想這樣的事:

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

不用說,但這並不是完全的表現。

另外,請注意StackTrace類 - 當使用太頻繁時,它也是一個性能問題。

2

在聲明該方法的類中,可以搜索包含該setter的屬性。它不是高性能的,但也不是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

作爲一種替代方法,您可以考慮延遲驗證,直到晚點,因此不需要檢查堆棧跟蹤。

該實施例提供了一個屬性...

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

... POCO一個與施加到一個屬性屬性...

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

...和一個工具類存根驗證對象。

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

哦。從編碼的角度來看,我更喜歡這種方法。當然,除非實現驗證,否則屬性修飾是無用的,在這個模型中稍微難以假設,但總體而言,它應該更快更乾淨。 – 2010-09-02 16:41:19

+0

你能告訴我如何驗證這個值與atts的對應關係嗎?謝謝! – VladL 2013-11-06 15:40:34