代码之家  ›  专栏  ›  技术社区  ›  Ben McCormack

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

  •  5
  • Ben McCormack  · 技术社区  · 14 年前

    注意:这是对 answer 在一 previous question .

    我正在用名为 TestMaxStringLength 在从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 负责查找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.
    }
    

    我怎么换 验证属性 代码以查找 财产 而不是 集合方法 ?

    3 回复  |  直到 14 年前
        1
  •  7
  •   user438034    14 年前

    据我所知,无法从其设置者之一的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
  •  2
  •   Chris Schmich    14 年前

    在声明方法的类中,可以搜索包含该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.
    }
    
        3
  •  2
  •   kbrimington    14 年前

    您可以考虑,作为一种替代方法,将验证延迟到稍后,从而消除了检查堆栈跟踪的需要。

    此示例提供了一个属性…

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