Можно ли создать атрибут, который может быть инициализирован переменным числом аргументов?
Например:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Можно ли создать атрибут, который может быть инициализирован переменным числом аргументов?
Например:
[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
{
}
Да, но вам нужно инициализировать массив, в котором вы проходите. Вот пример из теста строк в наших модульных тестах, который проверяет переменное количество параметров командной строки;
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
Вы можете это сделать. Другим примером может быть:
class MyAttribute: Attribute
{
public MyAttribute(params object[] args)
{
}
}
[MyAttribute("hello", 2, 3.14f)]
class Program
{
static void Main(string[] args)
{
}
}
Чтобы ответить на ответ Марка Гравелла, да, вы можете определить атрибут с параметрами массива, но применение атрибута с параметром массива не соответствует CLS. Однако просто определение атрибута с свойством array отлично соответствует CLS.
Что заставило меня понять, что Json.NET, CLS-совместимая библиотека, имеет класс атрибута JsonPropertyAttribute с свойством ItemConverterParameters, который представляет собой массив объектов.