Можно ли создать атрибут, который можно инициализировать с переменным количеством аргументов?
Например:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Ответы:
Атрибуты примут массив. Хотя, если вы контролируете атрибут, вы также можете использовать params
вместо него (что лучше для потребителей, IMO):
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(3, 4, 5)]
class MyClass { }
Ваш синтаксис для создания массива просто отключен:
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
Вы можете это сделать, но это не соответствует требованиям CLS:
[assembly: CLSCompliant(true)]
class Foo : Attribute
{
public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}
Показывает:
Warning 1 Arrays as attribute arguments is not CLS-compliant
Для регулярного использования отражения может быть предпочтительнее иметь несколько атрибутов, т.е.
[Foo("abc"), Foo("def")]
Однако это не будет работать с TypeDescriptor
/ PropertyDescriptor
, где поддерживается только один экземпляр любого атрибута (выигрывает первый или последний, я не могу вспомнить какой).
Попробуйте объявить конструктор следующим образом:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
Тогда вы можете использовать это как:
[MyCustomAttribute(3, 4, 5)]
Это должно быть нормально. Из спецификации, раздел 17.2:
Выражение E является выражением- атрибут-аргумент, если все следующие утверждения верны:
Вот пример:
using System;
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
public SampleAttribute(int[] foo)
{
}
}
[Sample(new int[]{1, 3, 5})]
class Test
{
}
Чтобы воспользоваться ответом Марка Гравелла, да, вы можете определить атрибут с параметрами массива, но применение атрибута с параметром массива несовместимо с CLS. Однако просто определение атрибута с помощью свойства массива полностью соответствует требованиям CLS.
Я понял, что это Json.NET, библиотека, совместимая с CLS, имеет класс атрибутов JsonPropertyAttribute со свойством с именем ItemConverterParameters, которое представляет собой массив объектов.