2010-09-02 30 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