如何在运行时读取类的属性?

Zaf*_*iro 98 c# generics custom-attributes

我正在尝试创建一个通用方法,该方法将读取类的属性并在运行时返回该值.我该怎么做?

注意:DomainName属性属于DomainNameAttribute类.

[DomainName("MyTable")]
Public class MyClass : DomainBase
{}
Run Code Online (Sandbox Code Playgroud)

我想要生成的内容:

//This should return "MyTable"
String DomainNameValue = GetDomainName<MyClass>();
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 218

public string GetDomainName<T>()
{
    var dnAttribute = typeof(T).GetCustomAttributes(
        typeof(DomainNameAttribute), true
    ).FirstOrDefault() as DomainNameAttribute;
    if (dnAttribute != null)
    {
        return dnAttribute.Name;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

更新:

可以进一步推广此方法以使用任何属性:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用这样的:

string name = typeof(MyClass)
    .GetAttributeValue((DomainNameAttribute dna) => dna.Name);
Run Code Online (Sandbox Code Playgroud)

  • 感谢您勤勉地回答这个问题! (6认同)
  • 过于复杂.无需使用lambda来选择属性值.如果你足够写lambda,你就知道只需要访问该字段. (3认同)
  • 此扩展方法可以通过扩展 MemberInfo、Type 的基类和所有(或至少*大多数*)Type 的成员来进一步概括。这样做将打开它以允许从属性、字段甚至事件中读取属性。 (2认同)

Dar*_*Lee 46

已经有一个扩展来做到这一点.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以:

var attr = typeof(MyClass).GetCustomAttribute<DomainNameAttribute>(false);
return attr != null ? attr.DomainName : "";
Run Code Online (Sandbox Code Playgroud)

  • 真的。但仅限 .NET 4.5 及更高版本。我仍在开发库代码,但无法使用此方法:( (2认同)

Mer*_*itt 13

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);
    }   
}
Run Code Online (Sandbox Code Playgroud)

  • 并且+1不使用"var",因此很容易理解它是如何工作的. (3认同)

Sev*_*in7 5

我使用 Darin Dimitrov 的答案创建了一个通用扩展来获取类中任何成员的成员属性(而不是类的属性)。我在这里发布它是因为其他人可能会发现它很有用:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

//Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass'
var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
Run Code Online (Sandbox Code Playgroud)