使用reflection通过从setter调用的方法获取属性的属性

注意:这是对上一个问题的答案的后续跟进

我正在使用名为TestMaxStringLength的属性来装饰属性的setter,该属性在setter调用的方法中用于validation。

该物业目前看起来像这样:

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

负责查找setter属性的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代码以查找属性而不是set方法属性

据我所知,没有办法从其中一个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类 – 当经常使用时,它也是一种性能损耗。

在声明方法的类中,您可以搜索包含该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. } 

作为一种替代方法,您可以考虑将validation延迟到以后,从而无需检查堆栈跟踪。

这个例子提供了一个属性……

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

…以及validation对象的实用程序类存根。

 public class PocoValidator { public static bool ValidateProperties(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; } }