Как передать объекты в конструктор атрибута - PullRequest
55 голосов
/ 06 августа 2009

Я пытаюсь передать объекты в конструктор атрибутов следующим образом:

[PropertyValidation(new NullOrEmptyValidatorScheme())]
public string Name { get; private set; }

С этим конструктором атрибута:

 public PropertyValidationAttribute(IValidatorScheme validator) {
      this._ValidatorScheme = validator;
    }

Код не скомпилируется. Как я могу передать объект в атрибут, как указано выше?

РЕДАКТИРОВАТЬ: Да NullOrEmptyValidatorScheme реализует IValidatorScheme.

Ошибка: ошибка CS0182: аргумент атрибута должен быть константным выражением, выражением typeof или выражением создания массива типа параметра атрибута.

Ответы [ 3 ]

68 голосов
/ 06 августа 2009

Значения в атрибутах ограничены простыми типами; например, основные константы (включая строки) и typeof ... вы не можете использовать new или другой более сложный код. Короче; ты не можешь сделать это Вы можете дать ему тип , хотя:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)]

т.е. PropertyValidation ctor принимает Type и использует Activator.CreateInstance внутри кода для создания объекта. Обратите внимание, что в идеале вы должны просто хранить строку внутри (AssemblyQualifiedName).

Из ECMA 334v4:

§24.1.3 Типы параметров атрибута

Типы позиционных и именованных параметры для класса атрибута ограничено параметром типы , которые:

  • Один из следующих типов: bool, byte, char, double, float, int, long, short, string.
  • Тип object.
  • Тип System.Type.
  • Тип enum, если он общедоступен и типы, в которые он вложен (если есть) также имеют общедоступную доступность.
  • одномерные массивы выше типы.

и

§24.2 Спецификация атрибута

...

Выражение E является атрибут-аргумент-выражение, если все из следующих утверждений верны:

  • Тип E является атрибутом тип параметра (§24.1.3).
  • Во время компиляции значение E может быть решено к одному из следующих:
    • Постоянное значение.
    • typeof-выражение (§14.5.11), указывающее неуниверсальное тип, закрытого сконструированного типа (§25.5.2), или несвязанный универсальный тип (§25.5).
    • Одномерный массив атрибут-аргументов-выражений.
10 голосов
/ 06 августа 2009

Как отмечалось в предыдущих постерах, типы, используемые в аргументах атрибутов, довольно строго ограничены (понятно, потому что их значения необходимо сериализовать непосредственно в блок метаданных сборки).

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

Например:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme))]
public string Name { get; private set; }

Этот синтаксис совершенно легален. Код, который читает ваши атрибуты, должен получить тип валидатора, создать новый экземпляр валидатора (он может даже поддерживать кеш валидаторов, привязанный к типам валидатора, если это уместно - это довольно распространенный метод), а затем вызвать его .

5 голосов
/ 29 марта 2012

Также ... (я думаю, что это ошибка Microsoft)

Вы не можете установить значение по умолчанию в «null», но простое значение по умолчанию в порядке («false», «7», «Test»).

Пример NExt выдаст вам следующую ошибку: Аргумент атрибута должен быть выражением константы, выражением typeof или выражением создания массива типа параметра атрибута
в файле: ... \ CSC

public class SampleAttribute : Attribute
{
    private string _test;
    public SampleAttribute(string test = null)
    {
        _test = test;
    }
}

[Sample]
public class Toto
{

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...