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