2008-11-28 15 views
6

Potrzebuję właściwość Guid w niektóre klasy atrybutu jak poniżej:Jak wziąć identyfikator GUID jako parametr atrybutu?

public class SomeAttribute : Attribute { 
    private Guid foreignIdentificator; 
    public Guid ForeignIdentificator { 
     get { return this.foreignIdentificator; } 
     set { this.foreignIdentificator = value; } 
    } 
} 

Ale w definicji atrybutu można użyć tylko prymitywne typy, które są stałymi (rozumiem dlaczego, i to mnie sens). Rozwiązaniem może być definicja „ForeignIdentificator” jako ciąg i tworzenia Guid w czasie wykonywania:

public class SomeAttribute : Attribute { 
    private string foreignIdentificator; 
    public string ForeignIdentificator { 
     get { return this.foreignIdentificator; } 
     set { this.foreignIdentificator = value; } 
    } 
    public Guid ForeignIdentificatorGuid { 
     get { return new Guid(ForeignIdentificator); } 
    } 
} 

Unahppily stracę sprawdzenia bezpieczeństwa typu. Właściwość "ForeignIdentificator" może zawierać dowolną wartość ciągu, a podczas tworzenia Guid zostanie zgłoszony wyjątek w czasie wykonywania, a nie podczas kompilacji.

Wiem, że kompilator sprawdza wartość ciągu dla "System.Runtime.InteropServices.GuidAttribute" dla "zgodności z Guid". Ta kontrola jest dokładnie tym, czego potrzebuję, ale nie wiem, czy to sprawdzanie zostało zakodowane na stałe w kompilatorze, czy też mogę je jednoznacznie zdefiniować (i jak).

Czy znasz jakiś sposób, w jaki sposób sprawdzić atrybut "Guid compatibilty" dla atrybutów? Lub w inny sposób, jak osiągnąć bezpieczny atrybut Guid w atrybutach? Dzięki.

+0

Co to jest "Identyfikator"? –

+0

"ForeignIdentificator" to wartość typu GUID zdefiniowana w innym zespole lub bazie danych lub w jakimkolwiek innym miejscu, do której należy dodać właściciela atrybutu. – TcKs

+0

To brzmi jak krzew. – xr280xr

Odpowiedz

6

W przeszłości napotkałem na twój problem. Po prostu wymagaliśmy od nich przekazywania identyfikatora GUID jako ciągu znaków ... domyślny sposób, jaki daje nam narzędzie generatora GUID VS (* F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4). Zasadniczo zrobiliśmy to, co zrobiłeś. Używamy go w architekturze wtyczek, więc nasi klienci używali tego interfejsu. Jeśli spojrzysz na to, co robi Microsoft, kiedy muszą zrobić to samo, robią to.

Wykonanie tego w ten sposób nie było problemem. Nie raz, widzieliśmy to jako problem z pola.

Możesz jednak nazwać to pole GUID łańcucha znaków, aby nie mylić swoich klientów. Dodaj dokumentację na wypadek, gdyby nie wiedział, w jakim formacie powinien być.

Miałem taką samą reakcję, gdy na to patrzyłem, ale potem po prostu przeniosłem się, ponieważ wydaje się, że nie ma typu. bezpieczne rozwiązanie.

+0

Pisanie nowego Guida nie stanowi dla mnie problemu (mam do tego kluczowy shourtcut), ale obawiam się innych ludzi. Ale jeśli nie ma sposobu, jak zabezpieczyć poprawny format w czasie kompilacji (i obawiam się, że nie ma), muszę utworzyć narzędzie, które przetestuje wszystkie definicje atrybutów w skompilowanym zestawie. – TcKs

+0

Rozumiem twoją troskę. Spędziliśmy też trochę czasu, próbując to rozgryźć. W implementacjach Microsoft robią to samo, więc daliśmy sobie spokój. Ponownie obawialiśmy się, że będzie to problem w tej dziedzinie, ale nie pojawił się jako problem. Tylko pamiętaj, aby złapać wyjątek na końcu. –

+0

Wyznajesz moje przypuszczenia. Nie będę więcej szukać innego rozwiązania. Dzięki. – TcKs

4

Parametry atrybutów muszą być stałe. Gdybym łamać zasady, mój kompilator C# daje ten błąd:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Ponieważ nie istnieją żadne GUID literały w C#, trzeba zakodować GUID w innym formacie, na przykład łańcuch. Jednak nie jesteś całkowicie na morzu: możesz sprawić, by atrybut miał ctor, który ma żądany format. Oto przykład z tymi samymi lekarzami, co System.Guid:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] 
sealed class MyGuidAttribute : Attribute 
{ 
    public Guid Guid { get; private set; } 

    // 
    // Summary: 
    //  Initializes a new instance of the System.Guid class using the specified array 
    //  of bytes. 
    // 
    // Parameters: 
    // b: 
    //  A 16 element byte array containing values with which to initialize the GUID. 
    // 
    // Exceptions: 
    // System.ArgumentNullException: 
    //  b is null. 
    // 
    // System.ArgumentException: 
    //  b is not 16 bytes long. 
    public MyGuidAttribute(byte[] b) 
    { 
     this.Guid = new Guid(b); 
    } 
    // 
    // Summary: 
    //  Initializes a new instance of the System.Guid class using the value represented 
    //  by the specified string. 
    // 
    // Parameters: 
    // g: 
    //  A System.String that contains a GUID in one of the following formats ('d' 
    //  represents a hexadecimal digit whose case is ignored): 32 contiguous digits: 
    //  dddddddddddddddddddddddddddddddd -or- Groups of 8, 4, 4, 4, and 12 digits 
    //  with hyphens between the groups. The entire GUID can optionally be enclosed 
    //  in matching braces or parentheses: dddddddd-dddd-dddd-dddd-dddddddddddd -or- 
    //  {dddddddd-dddd-dddd-dddd-dddddddddddd} -or- (dddddddd-dddd-dddd-dddd-dddddddddddd) 
    //  -or- Groups of 8, 4, and 4 digits, and a subset of eight groups of 2 digits, 
    //  with each group prefixed by "0x" or "0X", and separated by commas. The entire 
    //  GUID, as well as the subset, is enclosed in matching braces: {0xdddddddd, 
    //  0xdddd, 0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} All braces, commas, 
    //  and "0x" prefixes are required. All embedded spaces are ignored. All leading 
    //  zeroes in a group are ignored. The digits shown in a group are the maximum 
    //  number of meaningful digits that can appear in that group. You can specify 
    //  from 1 to the number of digits shown for a group. The specified digits are 
    //  assumed to be the low order digits of the group. 
    // 
    // Exceptions: 
    // System.ArgumentNullException: 
    //  g is null. 
    // 
    // System.FormatException: 
    //  The format of g is invalid. 
    // 
    // System.OverflowException: 
    //  The format of g is invalid. 
    public MyGuidAttribute(string g) 
    { 
     this.Guid = new Guid(g); 
    } 
    // 
    // Summary: 
    //  Initializes a new instance of the System.Guid class using the specified integers 
    //  and byte array. 
    // 
    // Parameters: 
    // a: 
    //  The first 4 bytes of the GUID. 
    // 
    // b: 
    //  The next 2 bytes of the GUID. 
    // 
    // c: 
    //  The next 2 bytes of the GUID. 
    // 
    // d: 
    //  The remaining 8 bytes of the GUID. 
    // 
    // Exceptions: 
    // System.ArgumentNullException: 
    //  d is null. 
    // 
    // System.ArgumentException: 
    //  d is not 8 bytes long. 
    public MyGuidAttribute(int a, short b, short c, byte[] d) 
    { 
     this.Guid = new Guid(a, b, c, d); 
    } 
    // 
    // Summary: 
    //  Initializes a new instance of the System.Guid class using the specified integers 
    //  and bytes. 
    // 
    // Parameters: 
    // a: 
    //  The first 4 bytes of the GUID. 
    // 
    // b: 
    //  The next 2 bytes of the GUID. 
    // 
    // c: 
    //  The next 2 bytes of the GUID. 
    // 
    // d: 
    //  The next byte of the GUID. 
    // 
    // e: 
    //  The next byte of the GUID. 
    // 
    // f: 
    //  The next byte of the GUID. 
    // 
    // g: 
    //  The next byte of the GUID. 
    // 
    // h: 
    //  The next byte of the GUID. 
    // 
    // i: 
    //  The next byte of the GUID. 
    // 
    // j: 
    //  The next byte of the GUID. 
    // 
    // k: 
    //  The next byte of the GUID. 
    public MyGuidAttribute(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) 
    { 
     this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k); 
    } 
    // 
    // Summary: 
    //  Initializes a new instance of the System.Guid class using the specified unsigned 
    //  integers and bytes. 
    // 
    // Parameters: 
    // a: 
    //  The first 4 bytes of the GUID. 
    // 
    // b: 
    //  The next 2 bytes of the GUID. 
    // 
    // c: 
    //  The next 2 bytes of the GUID. 
    // 
    // d: 
    //  The next byte of the GUID. 
    // 
    // e: 
    //  The next byte of the GUID. 
    // 
    // f: 
    //  The next byte of the GUID. 
    // 
    // g: 
    //  The next byte of the GUID. 
    // 
    // h: 
    //  The next byte of the GUID. 
    // 
    // i: 
    //  The next byte of the GUID. 
    // 
    // j: 
    //  The next byte of the GUID. 
    // 
    // k: 
    //  The next byte of the GUID. 
    [CLSCompliant(false)] 
    public MyGuidAttribute(uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) 
    { 
     this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k); 
    } 
} 
+0

Masz rację. Używam łańcucha, aby przekazać guidowi również atrybut. – IlPADlI