Как взять GUID в качестве параметра атрибута?

мне нужно свойство Guid в некотором классе атрибутов, как это:

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

но в определении атрибута я могу использовать только примитивные типы, которые являются константами (я понимаю, почему, и это имеет смысл ). Обходным путем может быть определение "ForeignIdentificator" как string и создание Guid во время выполнения:

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 я освобождаю проверку для типа безопасности. Свойство "ForeignIdentificator" может содержать любое строковое значение и при создании Guid будет выдаваться исключение во время выполнения, а не во время компиляции.

Я знаю, что компилятор проверяет строковое значение для " System.Во время выполнения.InteropServices.GuidAttribute " для "совместимости Guid". Эта проверка-именно то, что мне нужно, но я не знаю, является ли эта проверка жестко закодированной в компиляторе или может быть явно определена ( и как ).

знаете ли вы каким-то образом, как обеспечить проверку совместимости Guid для атрибутов? Или каким-то другим способом, как достичь определения типа safe Guid в атрибутах? Спасибо.

2 ответов


Я столкнулся с вашей точной проблемой в прошлом. Мы просто требовали, чтобы они передавали GUID как строку... по умолчанию инструмент генератора VS GUID предоставляет его нам (*F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4). Мы сделали то же, что и вы. Мы используем его в архитектуре плагина, поэтому наши клиенты были теми, кто использовал интерфейс. Если вы посмотрите, что делает Microsoft, когда им нужно сделать то же самое, они делают это.

Это не было проблемой, чтобы сделать это путь. Ни разу мы не рассматривали это как проблему с места.

вы можете назвать это строковое поле GUID, хотя, чтобы не запутать ваших потребителей. Добавьте некоторую документацию, если они не знают, в каком формате она должна быть.

У меня была такая же реакция, когда я посмотрел на это... но потом я просто двинулся дальше, так как, похоже, нет безопасного решения.


параметры атрибута должны быть постоянными. Если я нарушаю правила, мой компилятор C# выдает эту ошибку:

аргумент атрибута должен быть постоянным выражением, выражением типа или выражением создания массива типа параметра атрибута

поскольку в C# нет литералов GUID, вы должны кодировать GUID в другом формате, например, строку. Однако вы не полностью в море: вы можете сделать свой атрибут с ctor, который принимает формат, который вы хотите. Вот пример с теми же ctors, что и 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);
    }
}