可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to create a generic method that will read an attribute on a class and return that value at runtime. How do would I do this?
Note: DomainName attribute is of class DomainNameAttribute.
[DomainName("MyTable")]
Public class MyClass : DomainBase
{}
What I am trying to generate:
//This should return "MyTable"
String DomainNameValue = GetDomainName<MyClass>();
回答1:
public string GetDomainName<T>()
{
var dnAttribute = typeof(T).GetCustomAttributes(
typeof(DomainNameAttribute), true
).FirstOrDefault() as DomainNameAttribute;
if (dnAttribute != null)
{
return dnAttribute.Name;
}
return null;
}
UPDATE:
This method could be further generalized to work with any attribute:
public static class AttributeExtensions
{
public static TValue GetAttributeValue<TAttribute, TValue>(
this Type type,
Func<TAttribute, TValue> valueSelector)
where TAttribute : Attribute
{
var att = type.GetCustomAttributes(
typeof(TAttribute), true
).FirstOrDefault() as TAttribute;
if (att != null)
{
return valueSelector(att);
}
return default(TValue);
}
}
and use like this:
string name = typeof(MyClass)
.GetAttributeValue((DomainNameAttribute dna) => dna.Name);
回答2:
There is already an extension to do this.
namespace System.Reflection
{
// Summary:
// Contains static methods for retrieving custom attributes.
public static class CustomAttributeExtensions
{
public static T GetCustomAttribute<T>(this MemberInfo element, bool inherit) where T : Attribute;
}
}
So:
var attr = typeof(MyClass).GetCustomAttribute<DomainNameAttribute>(false);
return attr != null ? attr.DomainName : "";
回答3:
System.Reflection.MemberInfo info = typeof(MyClass);
object[] attributes = info.GetCustomAttributes(true);
for (int i = 0; i < attributes.Length; i++)
{
if (attributes[i] is DomainNameAttribute)
{
System.Console.WriteLine(((DomainNameAttribute) attributes[i]).Name);
}
}
回答4:
I used Darin Dimitrov's answer to create a generic extension to get member attributes for any member in a class (instead of attributes for a class). I'm posting it here because others may find it useful:
public static class AttributeExtensions
{
/// <summary>
/// Returns the value of a member attribute for any member in a class.
/// (a member is a Field, Property, Method, etc...)
/// <remarks>
/// If there is more than one member of the same name in the class, it will return the first one (this applies to overloaded methods)
/// </remarks>
/// <example>
/// Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass':
/// var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
/// </example>
/// <param name="type">The class that contains the member as a type</param>
/// <param name="MemberName">Name of the member in the class</param>
/// <param name="valueSelector">Attribute type and property to get (will return first instance if there are multiple attributes of the same type)</param>
/// <param name="inherit">true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events</param>
/// </summary>
public static TValue GetAttribute<TAttribute, TValue>(this Type type, string MemberName, Func<TAttribute, TValue> valueSelector, bool inherit = false) where TAttribute : Attribute
{
var att = type.GetMember(MemberName).FirstOrDefault().GetCustomAttributes(typeof(TAttribute), inherit).FirstOrDefault() as TAttribute;
if (att != null)
{
return valueSelector(att);
}
return default(TValue);
}
}
Usage example:
//Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass'
var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
回答5:
Here's a good tutorial if you haven't seen it before http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
In particular of interest to you is the section here, called Accessing the Attribute
http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx#vcwlkattributestutorialanchor3
回答6:
A simplified version of Darin Dimitrov's first solution:
public string GetDomainName<T>()
{
var dnAttribute = typeof(T).GetCustomAttribute<DomainNameAttribute>(true);
if (dnAttribute != null)
{
return dnAttribute.Name;
}
return null;
}
回答7:
' Simplified Generic version.
Shared Function GetAttribute(Of TAttribute)(info As MemberInfo) As TAttribute
Return info.GetCustomAttributes(GetType(TAttribute), _
False).FirstOrDefault()
End Function
' Example usage over PropertyInfo
Dim fieldAttr = GetAttribute(Of DataObjectFieldAttribute)(pInfo)
If fieldAttr IsNot Nothing AndAlso fieldAttr.PrimaryKey Then
keys.Add(pInfo.Name)
End If
Probably just as easy to use the body of generic function inline.
It doesn't make any sense to me to make the function generic over the type MyClass.
string DomainName = GetAttribute<DomainNameAttribute>(typeof(MyClass)).Name
// null reference exception if MyClass doesn't have the attribute.