如何将属性的.NET反射与每个对象相关联?

时间:2011-01-13 01:19:30

标签: c# reflection inheritance attributes types

如何使用反射来确定在每个继承级别应用哪个属性?

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

2 个答案:

答案 0 :(得分:6)

对继承链中的每个类型调用GetCustomAttributes,并为inherited参数传递false。

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 :(得分:1)

如果你希望能够获得在类型也实现的接口上声明的自定义属性以及它的继承链上的自定义属性,这是一种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;
};

此函数类似于Josh的答案,但返回IEnumerable<Type>,您可以将其与任何linq表达式一起使用。

其次,将继承链类型与所讨论的类型实现的接口类型连接起来。这给出了原始对象可以合法地转换为的完整类型列表。

最后构建一个以type为键的字典,并调用.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>