Как игнорировать цепочку наследования при получении атрибутов? - PullRequest
1 голос
/ 08 ноября 2008

Почему-то я этого не понимаю. (Пример модели ниже) Если я напишу:

var property = typeof(sedan).GetProperty("TurningRadius");
Attribute.GetCustomAttributes(property,typeof(MyAttribute), false)

вызов вернет MyAttribute (2), несмотря на указание, что я не хочу искать цепочку наследования. Кто-нибудь знает, какой код я могу написать, чтобы звонил

MagicAttributeSearcher(typeof(Sedan).GetProperty("TurningRadius"))

ничего не возвращает при звонке

MagicAttributeSearcher(typeof(Vehicle).GetProperty("TurningRadius"))

возвращает MyAttribute (1)?


Пример модели:

public class Sedan : Car
{
    // ...
}

public class Car : Vehicle
{
    [MyAttribute(2)]
    public override int TurningRadius { get; set; }
}

public abstract class Vehicle
{
    [MyAttribute(1)]
    public virtual int TurningRadius { get; set; }
}

Ответы [ 3 ]

4 голосов
/ 09 ноября 2008

Хорошо, учитывая дополнительную информацию, я считаю, что проблема в том, что GetProperty идет вверх по наследству.

Если вы измените свой звонок на GetProperty на:

PropertyInfo prop = type.GetProperty("TurningRadius",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

, тогда prop будет нулевым, если свойство не переопределено. Например:

static bool MagicAttributeSearcher(Type type)
{
    PropertyInfo prop = type.GetProperty("TurningRadius", BindingFlags.Instance | 
                                         BindingFlags.Public | BindingFlags.DeclaredOnly);

    if (prop == null)
    {
        return false;
    }
    var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
    return attr != null;
}

Возвращает true и только если:

  • Указанный тип переопределяет свойство TurningRadius (или объявляет новое)
  • Свойство имеет атрибут MyAttribute.
3 голосов
/ 09 ноября 2008

Я считаю, что проблема в том, что при получении свойства TurningRadius от объекта Sedan в первой строке

var property = typeof(sedan).GetProperty("TurningRadius");

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

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

Вы должны изменить GetProperty, чтобы добавить необходимые флаги для получения только объявленных членов. Я считаю, DeclaredOnly должен делать.

Редактировать: обратите внимание, что это изменение будет иметь первую строку, возвращающую нуль, поэтому следите за исключениями NullPointerExceptions.

1 голос
/ 08 ноября 2008

Я думаю, это то, что вам нужно - обратите внимание, что мне пришлось сделать TurningRadius абстрактным в Vehicle и переопределенным в Car. Это нормально?

using System;
using System.Reflection;

public class MyAttribute : Attribute
{
    public MyAttribute(int x) {}
}

public class Sedan : Car
{
    // ...
}

public class Car : Vehicle
{
    public override int TurningRadius { get; set; }
}

public abstract class Vehicle
{
    [MyAttribute(1)]
    public virtual int TurningRadius { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        MagicAttributeSearcher(typeof(Sedan));
        MagicAttributeSearcher(typeof(Vehicle));
    }

    static void MagicAttributeSearcher(Type type)
    {
        PropertyInfo prop = type.GetProperty("TurningRadius");
        var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
        Console.WriteLine("{0}: {1}", type, attr);
    }
}

Выход:

Sedan:
Vehicle: MyAttribute
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...