Frage Wie lese ich zur Laufzeit ein Attribut einer Klasse?


Ich versuche, eine generische Methode zu erstellen, die ein Attribut für eine Klasse liest und diesen Wert zur Laufzeit zurückgibt. Wie würde ich das tun?

Anmerkung: Das DomainName-Attribut hat die Klasse DomainNameAttribute. 

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

Was ich versuche zu generieren:

//This should return "MyTable"
String DomainNameValue = GetDomainName<MyClass>();

75
2018-04-16 21:25


Ursprung


Antworten:


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

AKTUALISIEREN:

Diese Methode könnte weiter verallgemeinert werden, um mit jedem Attribut zu arbeiten:

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

und verwende so:

string name = typeof(MyClass)
    .GetAttributeValue((DomainNameAttribute dna) => dna.Name);

173
2018-04-16 21:30



Es gibt bereits eine Erweiterung, um dies zu tun.

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

Damit:

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

23
2018-04-15 01:31



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

11
2018-04-16 21:31



Ich habe die Antwort von Darin Dimitrov verwendet, um eine generische Erweiterung zu erstellen, um Mitgliedsattribute für jedes Mitglied einer Klasse zu erhalten (anstelle von Attributen für eine Klasse). Ich poste es hier, weil andere es nützlich finden könnten:

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

Verwendungsbeispiel:

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

4
2017-11-26 12:00



Hier ist ein gutes Tutorial, wenn Sie es vorher nicht gesehen haben http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

Besonders interessant für Sie ist der Abschnitt namens Zugriff auf das Attribut http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx#vcwlkattributestutorialanchor3


2
2018-04-16 21:27



Eine vereinfachte Version von Darin Dimitrovs erster Lösung:

public string GetDomainName<T>()
{
    var dnAttribute = typeof(T).GetCustomAttribute<DomainNameAttribute>(true);
    if (dnAttribute != null)
    {
        return dnAttribute.Name;
    }
    return null;
}

2
2018-03-26 00:26



' 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

Wahrscheinlich so einfach, den Körper der generischen Funktion inline zu verwenden. Es macht für mich keinen Sinn, die Funktion über den Typ MyClass generisch zu machen.

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

0
2018-04-14 22:21