Как я могу соотнести .NET отражение атрибутов с каждым объектом? - PullRequest
1 голос
/ 13 января 2011

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

    var AttributeArray = gUser.GetType().GetCustomAttributes(true);

Ответы [ 2 ]

6 голосов
/ 13 января 2011

Вызвать GetCustomAttributes для каждого типа в цепочке наследования и передать false для параметра inherited.

Type t = gUser.GetType();

while (t != null && t != typeof(object)) {

    var attributes = t.GetCustomAttributes(false);

    // do something with this level of attributes

    t = t.BaseType;

}
1 голос
/ 13 января 2011

Если вы хотите иметь возможность также получать пользовательские атрибуты, объявленные на интерфейсах, которые тип также реализует в дополнение к атрибутам в его цепочке наследования, вот способ linq-ish сделать это.

Сначала получите цепочку наследования:

// recursive lambda functions must initially be
// assigned null to allow recursive calls 
Func<Type, IEnumerable<Type>> getInheritanceChain = null;
getInheritanceChain = t =>
{
    IEnumerable<Type> ts = new [] { t, };
    var bt = t.BaseType;
    if (bt != null)
    {
        ts = ts.Concat(getInheritanceChain(bt));
    }
    return ts;
};

Эта функция похожа на ответ Джоша, но возвращает IEnumerable<Type>, который можно использовать с любым выражением linq.

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

Наконец, создайте словарь с типом в качестве ключа и вызовом .GetCustomAttributes(false) для создания значений типа IEnumerable<Attribute>:

Func<Type, IDictionary<Type, Attribute[]>> getCustomAttributesByType = 
    t => getInheritanceChain(t)
        .Concat(t.GetInterfaces())
        .ToDictionary(
            x => x,
            x => x.GetCustomAttributes(false)
                .Cast<Attribute>()
                .ToArray());

Конечный результат - простой вызов для создания простого в использовании словаря.

IDictionary<Type, Attribute[]> lookup =
    getCustomAttributesByType(gUser.GetType());

Если он работает с System.String, словарь содержит следующие значения:

System.String
 -> System.Reflection.DefaultMemberAttribute
 -> System.Runtime.InteropServices.ComVisibleAttribute
 -> System.SerializableAttribute
System.Object
 -> System.Runtime.InteropServices.ComVisibleAttribute
 -> System.Runtime.InteropServices.ClassInterfaceAttribute
 -> System.SerializableAttribute
System.IComparable
 -> System.Runtime.InteropServices.ComVisibleAttribute
System.ICloneable
 -> System.Runtime.InteropServices.ComVisibleAttribute
System.IConvertible
 -> System.Runtime.InteropServices.ComVisibleAttribute
 -> System.CLSCompliantAttribute
System.IComparable<System.String>
System.Collections.Generic.IEnumerable<System.Char>
 -> System.Runtime.CompilerServices.TypeDependencyAttribute
System.Collections.IEnumerable
 -> System.Runtime.InteropServices.ComVisibleAttribute
 -> System.Runtime.InteropServices.GuidAttribute
System.IEquatable<System.String>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...