Czy Mogę zainicjalizować atrybut C# za pomocą tablicy lub innej zmiennej liczby argumentów?

Czy jest możliwe utworzenie atrybutu, który może być zainicjalizowany zmienną liczbą argumentów?

Na przykład:

[MyCustomAttribute(new int[]{ 3, 4, 5})]  // this doesn't work
public MyClass ...
Author: Rajmond Burgaj, 2008-11-06

7 answers

Atrybuty przyjmą tablicę. Chociaż jeśli kontrolujesz atrybut, możesz również użyć params zamiast tego (co jest ładniejsze dla konsumentów, IMO):

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(params int[] values) {
       this.Values = values;
    }
}

[MyCustomAttribute(3, 4, 5)]
class MyClass { }

Twoja składnia do tworzenia tablic jest wyłączona:

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(int[] values) {
        this.Values = values;
    }
}

[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
 150
Author: Mark Brackett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 15:56:19

Możesz to zrobić, ale nie jest to zgodne z CLS:

[assembly: CLSCompliant(true)]

class Foo : Attribute
{
    public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}

Pokazuje:

Warning 1   Arrays as attribute arguments is not CLS-compliant

Dla regularnego użycia odbicia, może być lepiej mieć wiele atrybutów, np.

[Foo("abc"), Foo("def")]

Jednak to nie zadziała z TypeDescriptor/PropertyDescriptor, gdzie obsługiwana jest tylko jedna instancja dowolnego atrybutu (pierwsza lub ostatnia wygrywa, nie pamiętam który).

 30
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 00:09:10

Spróbuj zadeklarować konstruktor TAK:

public class MyCustomAttribute : Attribute
{
    public MyCustomAttribute(params int[] t)
    {
    }
}

Wtedy możesz go użyć w następujący sposób:

[MyCustomAttribute(3, 4, 5)]

 16
Author: Scott Dorman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 20:49:50

Powinno być dobrze. Od spec, sekcja 17.2:

Wyrażenie E jest atrybutem-argumentem-wyrażeniem jeśli wszystkie poniższe wyrażenia są prawdziwe:

  • typ E jest typem parametru atrybutowego (§17.1.3).
  • w czasie kompilacji wartość E może być rozwiązana do jednej z następujących wartości:
    • stała wartość.
    • System.Wpisz obiekt.
    • jednowymiarowa tablica atrybut-argument-wyrażenia .

Oto przykład:

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
{
}
 12
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 20:49:08

Tak, ale musisz zainicjować tablicę, którą przekazujesz. Oto przykład z testu wiersza w naszych testach jednostkowych, który testuje zmienną liczbę opcji wiersza poleceń;

[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
 4
Author: Rob Prouse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 20:48:45

Możesz to zrobić. Innym przykładem może być:

class MyAttribute: Attribute
{
    public MyAttribute(params object[] args)
    {
    }
}

[MyAttribute("hello", 2, 3.14f)]
class Program
{
    static void Main(string[] args)
    {
    }
}
 1
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 20:50:49

Aby odpowiedzieć na pytanie marca Gravella, tak można zdefiniować atrybut z parametrami array, ale zastosowanie atrybutu z parametrem array nie jest zgodne z CLS. Jednak samo zdefiniowanie atrybutu z właściwością array jest całkowicie zgodne z CLS.

Uświadomiłem sobie, że Json.NET biblioteka zgodna z CLS posiada atrybut klasy JsonPropertyAttribute z właściwością ItemConverterParameters, która jest tablicą obiektów.

 1
Author: TBrink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 14:39:50