Přístupové atributy pomocí reflexe

Skutečnost, že můžete definovat vlastní atributy a umístit je do zdrojového kódu, by byla malá hodnota bez nějakého způsobu načtení těchto informací a jednání s nimi. Pomocí reflexe můžete načíst informace definované pomocí vlastních atributů. Metoda klíče je GetCustomAttributes, která vrací pole objektů, které jsou ekvivalenty runtime atributů zdrojového kódu. Tato metoda má mnoho přetížených verzí. Další informace najdete na webu Attribute.

Specifikace atributu, například:

[Author("P. Ackerman", Version = 1.1)]
class SampleClass { }

je koncepčně ekvivalentní následujícímu kódu:

var anonymousAuthorObject = new Author("P. Ackerman")
{
    Version = 1.1
};

Kód se však nespustí, dokud SampleClass se nezotáže na atributy. SampleClass Volání GetCustomAttributes způsobí vytvoření a inicializaci objektuAuthor. Pokud třída má další atributy, další objekty atributů jsou vytvořené podobně. GetCustomAttributes pak vrátí Author objekt a všechny ostatní objekty atributů v poli. Pak můžete iterovat přes toto pole, určit, jaké atributy byly použity na základě typu každého prvku pole a extrahovat informace z objektů atributů.

Tady je úplný příklad. Vlastní atribut je definován, použit na několik entit a načten prostřednictvím reflexe.

// Multiuse attribute.
[System.AttributeUsage(System.AttributeTargets.Class |
                       System.AttributeTargets.Struct,
                       AllowMultiple = true)  // Multiuse attribute.
]
public class AuthorAttribute : System.Attribute
{
    string Name;
    public double Version;

    public AuthorAttribute(string name)
    {
        Name = name;

        // Default value.
        Version = 1.0;
    }

    public string GetName() => Name;
}

// Class with the Author attribute.
[Author("P. Ackerman")]
public class FirstClass
{
    // ...
}

// Class without the Author attribute.
public class SecondClass
{
    // ...
}

// Class with multiple Author attributes.
[Author("P. Ackerman"), Author("R. Koch", Version = 2.0)]
public class ThirdClass
{
    // ...
}

class TestAuthorAttribute
{
    public static void Test()
    {
        PrintAuthorInfo(typeof(FirstClass));
        PrintAuthorInfo(typeof(SecondClass));
        PrintAuthorInfo(typeof(ThirdClass));
    }

    private static void PrintAuthorInfo(System.Type t)
    {
        System.Console.WriteLine($"Author information for {t}");

        // Using reflection.
        System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t);  // Reflection.

        // Displaying output.
        foreach (System.Attribute attr in attrs)
        {
            if (attr is AuthorAttribute a)
            {
                System.Console.WriteLine($"   {a.GetName()}, version {a.Version:f}");
            }
        }
    }
}
/* Output:
    Author information for FirstClass
       P. Ackerman, version 1.00
    Author information for SecondClass
    Author information for ThirdClass
       R. Koch, version 2.00
       P. Ackerman, version 1.00
*/

Viz také