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);
}
}
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.
See more on this question at Stackoverflow