makerofthings7
makerofthings7

Reputation: 61433

How can I correlate .NET reflection of attributes with each object?

How can I use reflection to determine what attribute is applied at each level of inheritance?

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

Upvotes: 1

Views: 390

Answers (2)

Enigmativity
Enigmativity

Reputation: 117037

If you want to be able to also get custom attributes declared on the interfaces that the type also implements in addition to those on its inheritance chain here's a linq-ish way to do it.

First, get the inheritance chain:

// 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;
};

This function is similar to Josh's answer but returns an IEnumerable<Type> that you can use with any linq expression.

Second, concatenate the inheritance chain types with the interface types implemented by the type in question. This gives the complete list of types that the original object can be legally cast to.

Finally build a dictionary with type as the key and calls to .GetCustomAttributes(false) to create values of type IEnumerable<Attribute>:

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

The end result is a simple call to build an easy to use dictionary.

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

If it's run against System.String the dictionary contains these values:

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>

Upvotes: 1

Josh
Josh

Reputation: 69262

Call GetCustomAttributes on each type in the inheritance chain and pass false for the inherited parameter.

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;

}

Upvotes: 6

Related Questions