Use reflection to get attribute of a property via method called from the setter

后端 未结 3 1055
长发绾君心
长发绾君心 2021-01-03 03:48

Note: This is a follow-up to an answer on a previous question.

I\'m decorating a property\'s setter with an Attribute called TestMaxStringLength

相关标签:
3条回答
  • 2021-01-03 04:03

    As far as I know, there's no way to get a PropertyInfo from a MethodInfo of one of its setters. Though, of course, you could use some string hacks, like using the name for the lookup, and such. I'm thinking something like:

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

    Needless to say, though, that's not exactly performant.

    Also, be careful with the StackTrace class - it's a performance hog, too, when used too often.

    0 讨论(0)
  • 2021-01-03 04:03

    You could consider, as an alternative approach, delaying validation until later, thus removing the need to inspect the stack trace.

    This example provides an attribute...

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

    ... a POCO with the attribute applied to a property...

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

    ... and a utility class stub that validates the object.

    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 讨论(0)
  • 2021-01-03 04:05

    In the class that declares the method, you could search for the property that contains that setter. It's not performant, but neither is 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.
    }
    
    0 讨论(0)
提交回复
热议问题