Pregunta

I have an attribute

[System.AttributeUsage(System.AttributeTargets.Class]
public class ModuleValues : System.Attribute
{
    public Guid? Id { get; set; }

    public ModuleValues(string id)
    {
        Id = Guid.Parse(id);
    }
}

How can I create a generic method that returns the attribute once found?

public static T GetAttribute<T>(Type type) where T : Attribute
{
    object[] attrs = typeof(T).GetCustomAttributes(true);
    foreach (Attribute attr in attrs)
    {
        if (attr.GetType() == typeof (T))
        {
            //Console.WriteLine(attr.ToString());
            return attr as T;
        }
    }

    return default(T);
}

With the constraint in place, my method always returns null.

When I remove the constraint, I can find the attribute with a Console.WriteLine but cannot return it because the line return attr as T; gives compile error The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint

Example usage from my console:

Assembly x = Assembly.GetAssembly(typeof(MyBase));

Type[] types = x.GetTypes();
foreach (Type type in types)
{
    if (type.IsSubclassOf(typeof (MyBase)))
    {
        ModuleValues s = CustomAttributeHelper.GetAttribute<ModuleValues>(type);
        Console.WriteLine("S" + s);
    }
}
¿Fue útil?

Solución

This line is the problem:

object[] attrs = typeof(T).GetCustomAttributes(true);

You're calling GetCustomAttributes on Type - not on the type that you're actually interested in. You want:

object[] attrs = type.GetCustomAttributes(true);

Or rather more simply, replace the rest of the method with:

return (T) type.GetCustomAttributes(typeof(T), true).FirstOrDefault();

Note that that will also pick up attributes which are subclasses of T, but I'd expect that to be more useful anyway, in the rare cases where you're actually using inheritance on attributes.

Otros consejos

This should be:

object[] attrs = type.GetCustomAttributes(true);

Changing typeof(T) to input type. The GetCustomAttributes method gets attributes ON the called type.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top