Definiowanie oraz odczyt własnych atrybutów

2012-10-21

Platforma .NET pozwala na definiowanie metadanych, czyli pewnych informacji opisujących różne elementy kodu. Funkcjonalność ta realizowana jest poprzez atrybuty. Atrybuty używane mogą być do opisu takich elementów jak klasy, metody, zdarzenia, pola, właściwości oraz wielu innych. Oprócz szeregu zdefiniowanych atrybutów mamy możliwość tworzenia własnych. Aby to zrobić wystarczy utworzyć klasę dziedziczącą po klasie System.Attribute. Klasa taka musi posiadać atrybut o nazwie AttributeUsage określający dwie rzeczy: do jakich elementów tworzony przez nas atrybut może być stosowany (enum AttributeTargets) oraz czy możliwe będzie użycie kilku takich atrybutów w jednym elemencie (AllowMultiple). Do naszego atrybutu możemy przekazywać dwa rodzaje argumentów: pozycyjne oraz nazwane. Argumenty pozycyjne przekazywane są poprzez konstruktor klasy w kolejności zgodnej z deklaracją jego parametrów, argumenty nazwane implementowane są jako pola lub właściwości i przekazywane poprzez nazwę. Poniższy przykład zawiera definicje dwóch własnych atrybutów: DBTable oraz DBColumn. Pierwszy z nich określa tabelę oraz schemat w bazie danych i może być stosowany dla klas, drugi określa nazwę i typ kolumny w tabeli bazy danych i może być użyty przy polach oraz właściwościach:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class DBTable : Attribute
{
    public string Name { get; private set; }
    public string Schema { get; set; }

    public DBTable(string name)
    {
        this.Name = name;
    }
}

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class DBColumn : Attribute
{
    public string Name { get; private set; }
    public DbType DataType { get; set; }

    public DBColumn(string name)
    {
        this.Name = name;
    }
}

A oto przykład użycia utworzonych atrybutów:

[DBTable("Osoba", Schema = "dbo")]
public class Person
{
    [DBColumn("Imie", DataType = DbType.String)]
    public string FirstName { get; set; }

    [DBColumn("Nazwisko", DataType = DbType.String)]
    public string LastName { get; set; }
}

Samo zdefiniowanie i użycie atrybutu niewiele nam da, jeżeli nie będziemy w stanie odczytać umieszczonych w nim informacji. W tym celu możemy posłużyć się mechanizmem odzwierciedlenia (System.Reflection). Poniższy kod poprzez klasy MemberInfo i PropertyInfo oraz metodę GetCustomAttributes pozwala na odczyt informacji umieszczonych w atrybutach (możemy także użyć statycznej klasy Attribute i jej metody GetCustomAttributes):

static void Main(string[] args)
{
    Person person = new Person { FirstName = "Jan", LastName = "Kowalski" };

    //Odczyt informacji o klasie (atrybut DBTable)
    MemberInfo personInfo = person.GetType();
    object[] personAttributes = personInfo.GetCustomAttributes(typeof(DBTable), false);
    if (personAttributes.Length > 0)
    {
        DBTable personAttribute = (DBTable)personAttributes[0];
        Console.WriteLine("Tabela: " + personAttribute.Name);
        Console.WriteLine("Schemat: " + personAttribute.Schema);
    }

    //Odczyt informacji o polu (atrybut DBColumn)
    PropertyInfo firstNameInfo = person.GetType().GetProperty("FirstName");
    object[] firstNameAttributes =
        firstNameInfo.GetCustomAttributes(typeof(DBColumn), false);
    if (firstNameAttributes.Length > 0)
    {
        DBColumn firstNameAttribute = (DBColumn)firstNameAttributes[0];
        Console.WriteLine("Kolumna: " + firstNameAttribute.Name);
        Console.WriteLine("Typ: " + firstNameAttribute.DataType.ToString());
    }

    Console.ReadLine();
}

Więcej informacji o definiowaniu własnych atrybutów: Attribute Class, AttributeUsageAttribute ClassAttributeTargets Enumeration.

Reklamy

Posted on 2012-10-21, in .NET/C# and tagged , , , . Bookmark the permalink. 2 Komentarze.

  1. Wg mnie lepiej użyć statycznej metody Attribute.GetCustomAttributes(). Swojego czasu nieźle się głowiłem, czemu metoda GetCustomAttributes z klasy Member nie widzi atrybutów dziedziczonych. Odpowiedź oczywiście znajduje się na MSDN.

    http://msdn.microsoft.com/en-us/library/dwc6ew1d(v=vs.90).aspx
    This method ignores the inherit parameter for properties and events. To search the inheritance chain for attributes on properties and events, use the appropriate overloads of the Attribute.GetCustomAttributes method.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: