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

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

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

Но в определении атрибутов я могу использовать только примитивные типы, которые являются константами (я понимаю, почему, и это дает мне смысл). Обходной путь может заключаться в определении "ForeignIdentificator" как строки и создании 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 ); }
    }
}

К сожалению, я потерял проверку на безопасность типов. Свойство «ForeignIdentificator» может содержать любое строковое значение, и во время создания Guid будет выдано исключение во время выполнения, а не во время компиляции.

Я знаю, что компилятор проверяет строковое значение для «System.Runtime.InteropServices.GuidAttribute» на «совместимость с Guid». Эта проверка - именно то, что мне нужно, но я не знаю, жестко ли я запрограммирована в компиляторе, или я могу ее явно определить (и как).

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

«ForeignIdentificator» - это значение GUID, которое определено в другой сборке, базе данных или в другом месте, куда следует добавить владельца атрибута.

TcKs 28.11.2008 16:33

Это похоже на бушизм.

xr280xr 26.01.2018 22:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
2
8 606
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

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

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

Написание нового руководства для меня не проблема (у меня есть для него ключевое слово), но я боюсь за других людей. Но если нет способа защитить правильный формат во время компиляции (а я боюсь, что это не так), я должен создать утилиту, которая будет проверять все определения атрибутов в скомпилированной сборке.

TcKs 28.11.2008 16:38

Я понимаю ваше беспокойство. Мы тоже потратили некоторое время, пытаясь понять это. В реализациях Microsoft они делают то же самое, поэтому мы сдались. Опять же, мы опасались, что это будет проблемой в полевых условиях, но ни разу не возникла как проблема. Просто убедитесь, что у вас есть исключение.

Brian Genisio 28.11.2008 16:43

Вы подтверждаете мою догадку. Я не буду больше искать другое решение. Спасибо.

TcKs 28.11.2008 16:57

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

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

Поскольку в 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);
    }
}

Ты прав. Я также использую строку для передачи идентификатора атрибуту.

IlPADlI 24.12.2016 17:28

Другие вопросы по теме