代码之家  ›  专栏  ›  技术社区  ›  Zaffiro

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

  •  85
  • Zaffiro  · 技术社区  · 14 年前

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

    注意:domainname属性属于domainname attribute类。

    [DomainName("MyTable")]
    Public class MyClass : DomainBase
    {}
    

    我要创造的是:

    //This should return "MyTable"
    String DomainNameValue = GetDomainName<MyClass>();
    
    7 回复  |  直到 9 年前
        1
  •  193
  •   Darin Dimitrov    14 年前
    public string GetDomainName<T>()
    {
        var dnAttribute = typeof(T).GetCustomAttributes(
            typeof(DomainNameAttribute), true
        ).FirstOrDefault() as DomainNameAttribute;
        if (dnAttribute != null)
        {
            return dnAttribute.Name;
        }
        return null;
    }
    

    更新:

    此方法可进一步推广到任何属性:

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

    像这样使用:

    string name = typeof(MyClass)
        .GetAttributeValue((DomainNameAttribute dna) => dna.Name);
    
        2
  •  30
  •   Darrel Lee    9 年前

    已经有一个扩展来执行此操作。

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

    所以:

    var attr = typeof(MyClass).GetCustomAttribute<DomainNameAttribute>(false);
    return attr != null ? attr.DomainName : "";
    
        3
  •  13
  •   Merritt    14 年前
    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
  •  4
  •   Sevin7 erikkallen    11 年前

    我使用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);
        }
    }
    

    用法示例:

    //Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass'
    var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
    
        5
  •  2
  •   Driss Zouak    14 年前

    如果你以前没看过的话,这里有一个很好的教程 http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

    您特别感兴趣的是这里的部分,称为访问属性 http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx#vcwlkattributestutorialanchor3

        6
  •  2
  •   jk7    9 年前

    Darin Dimitrov第一个解决方案的简化版本:

    public string GetDomainName<T>()
    {
        var dnAttribute = typeof(T).GetCustomAttribute<DomainNameAttribute>(true);
        if (dnAttribute != null)
        {
            return dnAttribute.Name;
        }
        return null;
    }
    
        7
  •  0
  •   Darrel Lee    9 年前
    ' 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
    

    可能与内联使用泛型函数体一样简单。 对我来说,将函数泛型化为myClass类型没有任何意义。

    string DomainName = GetAttribute<DomainNameAttribute>(typeof(MyClass)).Name
    // null reference exception if MyClass doesn't have the attribute.