Используйте отражение, чтобы получить атрибут свойства через метод, вызываемый из метода установки - PullRequest
5 голосов
/ 02 сентября 2010

Примечание. Это продолжение ответа на предыдущий вопрос .

Я украшаю установщик свойства Атрибутом с именем TestMaxStringLength, который используется в методе, вызываемом из установщика для проверки.

Свойство в настоящее время выглядит так:

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 для поиска атрибутов в свойстве вместо set set ?

Ответы [ 3 ]

7 голосов
/ 02 сентября 2010

Насколько я знаю, нет способа получить PropertyInfo из MethodInfo одного из его установщиков. Хотя, конечно, вы могли бы использовать некоторые строковые хаки, такие как использование имени для поиска и тому подобное. Я думаю что-то вроде:

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 голосов
/ 02 сентября 2010

В качестве альтернативного подхода можно было бы отложить проверку на более поздний срок, что устраняет необходимость в проверке трассировки стека.

В этом примере представлен атрибут ...

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;
    }
}
2 голосов
/ 02 сентября 2010

В классе, который объявляет метод, вы можете искать свойство, содержащее этот установщик.Это не является производительным, но не является 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.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...