2011-02-02 15 views

Odpowiedz

69

Chociaż kod utworzyć niestandardowy Attribute jest dość prosta, to znacznie ważne, aby zrozumieć, jakie są atrybuty:

atrybuty metadanych skompilowane do swojego programu. Same atrybuty nie dodają żadnej funkcjonalności do klasy, własności lub modułu, tylko dane. Jednak za pomocą refleksji można wykorzystać te atrybuty w celu stworzenia funkcjonalności.

Na przykład przyjrzyjmy się Validation Application Block, od Enterprise Library. Jeśli spojrzeć na przykład kodu, zobaczysz:

/// <summary> 
    /// blah blah code. 
    /// </summary> 
    [DataMember] 
    [StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")] 
    public string Code { get; set; } 

Od fragmencie powyżej, można się domyślać, że kod będzie zawsze być zatwierdzone, gdy zmienił się odpowiednio do zasad Validator (w tym przykładzie, mieć co najmniej 8 znaków i maksymalnie 8 znaków). Ale prawda jest taka, że ​​atrybut nic nie robi, tylko dodaje metadane do nieruchomości.

Jednak biblioteka korporacyjna ma metodę Validation.Validate, która zajmie się twoim obiektem, a dla każdej właściwości sprawdzi, czy zawartość narusza regułę informowaną przez atrybut.

A więc tak powinieneś pomyśleć o atrybutach - sposobie dodawania danych do kodu, które mogą być później użyte przez inne metody/klasy/etc.

+0

Czy naprawdę podoba mi się odpowiedź i specjalnie ", jeszcze jedno pytanie mogę umieścić ten sam warunek w zestawie instrukcji powyższego kodu, więc jak to różni się od atrybutów, –

+1

@slash: Czy możesz zmienić zdanie? Nie bardzo rozumiałem pytanie –

+1

Myślę, że slash miał na celu zapytać o różnicę między używaniem atrybutów i umieszczaniem rzeczywistego kodu walidacyjnego w ustawieniach właściwości. Odpowiedź: Podczas pisania kodu wewnątrz settera można zrobić, aby potwierdzić wartość, użycie samych atrybutów nie sprawdzi poprawności jako takiej. Atrybuty to tylko "meta-dane", a inny kod gdzieś indziej powinien być zainteresowany atrybutami, których używasz, czytać je i wykonywać działania na ich podstawie.Typowym przykładem jest biblioteka walidacji, jak wspomniano @BrunoBrant. – romar

190

zacząć pisząc klasę, która wynika z Attribute:

public class MyCustomAttribute: Attribute 
{ 
    public string SomeProperty { get; set; } 
} 

Następnie można ozdobić wszystko (klasa, metoda, nieruchomości, ...) z tego atrybutu:

[MyCustomAttribute(SomeProperty = "foo bar")] 
public class Foo 
{ 

} 

i na koniec użyjesz odbicia, aby go pobrać:

var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true); 
if (customAttributes.Length > 0) 
{ 
    var myAttribute = customAttributes[0]; 
    string value = myAttribute.SomeProperty; 
    // TODO: Do something with the value 
} 

Możesz ograniczyć liczbę typów docelowych do którego ten atrybut niestandardowy można zastosować przy użyciu atrybutu AttributeUsage:

/// <summary> 
/// This attribute can only be applied to classes 
/// </summary> 
[AttributeUsage(AttributeTargets.Class)] 
public class MyCustomAttribute : Attribute 

ważnych rzeczy wiedzieć o atrybutach:

  • atrybuty metadanych.
  • Są one pieczone w zestawie pod podczas kompilacji, co ma bardzo poważne konsekwencje, w jaki sposób można ustawić ich właściwości. Akceptowane są tylko wartości stałe (znane w czasie kompilacji).
  • Jedynym sposobem na uzyskanie jakiegokolwiek sensu i użycia atrybutów niestandardowych jest użycie Reflection. Więc jeśli nie używasz odbicia w czasie wykonywania, aby je pobrać i udekorować coś niestandardowym atrybutem, nie spodziewaj się, że wiele się wydarzy.
  • Czas tworzenia atrybutów jest niedeterministyczny. Są one tworzone przez CLR i nie masz absolutnej kontroli nad nim.
+1

Gdzie, w której funkcji/klasie, powinienem "użyć odbicia, aby go pobrać" –

+0

@Hasan A Yousef, na przykład w Entity Framework jest atrybut "Key", który mówi do frameworka: Ta właściwość powinna być traktowana jako klucz podstawowy . Podczas tworzenia ORM atrybuty są bardzo przydatne. – Parsa

+0

Jak uzyskać dostęp do niestandardowego atrybutu dla właściwości, a nie dla klasy? – Canvas

6

Wykorzystując/Kopiowanie Darin Dimitrov's great response, to w jaki sposób uzyskać dostęp do atrybutu niestandardowego na nieruchomości, a nie klasę:

zdobionej Właściwość [klasy Foo]:

[MyCustomAttribute(SomeProperty = "This is a custom property")] 
public string MyProperty { get; set; } 

Pobieranie go:

PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck); 
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true); 
if (attribute.Length > 0) 
{ 
    MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0]; 
    string propertyValue = myAttribute.SomeProperty; 
} 

Możesz rzucić to w pętlę i użyć odbicia, aby uzyskać dostęp do tego niestandardowego atrybutu na każdy własnością klasy Foo, a także:

foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties()) 
{ 
    string propertyName = propertyInfo.Name; 

    object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true); 
    // Just in case you have a property without this annotation 
    if (attribute.Length > 0) 
    { 
     MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0]; 
     string propertyValue = myAttribute.SomeProperty; 
     // TODO: whatever you need with this propertyValue 
    } 
} 

Główne dzięki wam, Darin !!

Powiązane problemy