2008-11-06 2 views

risposta

142

Gli attributi richiedono un array. Anche se controlli l'attributo, è anche possibile utilizzare params invece (che è più bello per i consumatori, IMO):

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

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

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

la sintassi per la creazione di matrice sembra appena essere fuori:

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

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

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

Sì, ma è necessario inizializzare l'array che si sta passando in Ecco un esempio da un test di fila nei nostri test di unità che mette alla prova un numero variabile di opzioni da linea di comando. ;

[Row(new[] { "-l", "/port:13102", "-lfsw" })] 
public void MyTest(string[] args) { //... } 
12

Che dovrebbe essere a posto. Dalla spec, sezione 17.2:

Un'espressione E è un attributo -argomento-espressione se tutte le seguenti affermazioni sono vere:

  • Il tipo di E è un tipo di parametro di attributo (§17.1 .3).
  • a tempo di compilazione, il valore di E può essere risolto a uno dei seguenti:
    • un valore costante.
    • Un oggetto System.Type.
    • Un array unidimensionale di attributo-argomento-espressioni.

Ecco un esempio:

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 
{ 
} 
+3

Attenzione per conformità CLS, anche se –

16

Prova dichiarando il costruttore in questo modo:

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

Quindi è possibile utilizzare le cose come:

[MyCustomAttribute(3, 4, 5)]

1

Puoi farlo. Un altro esempio potrebbe essere:

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

[MyAttribute("hello", 2, 3.14f)] 
class Program 
{ 
    static void Main(string[] args) 
    { 
    } 
} 
30

Puoi farlo, ma non è compatibile con CLS:

[assembly: CLSCompliant(true)] 

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

Spettacoli:

Warning 1 Arrays as attribute arguments is not CLS-compliant 

Per un utilizzo regolare della riflessione, potrebbe essere preferibile avere più attributi, ad esempio

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

Tuttavia, questo non funzionerà con TypeDescriptor/PropertyDescriptor, dove è supportato solo una singola istanza di qualsiasi attributo (o il primo o ultimo vince, non ricordo quale).

+3

nota: più attributi richiede un attributo AttributeUsage sull'attributo. http://stackoverflow.com/questions/553540/how-to-create-duplicate-allowed-attribute – russau

1

Per fare un passo indietro sulla risposta di Marc Gravell, sì è possibile definire un attributo con i parametri dell'array ma applicare un attributo con un parametro dell'array non è conforme a CLS. Tuttavia, la semplice definizione di un attributo con una proprietà array è perfettamente conforme a CLS.

Ciò che mi ha fatto capire è che Json.NET, una libreria compatibile con CLS, ha una classe di attributi JsonPropertyAttribute con una proprietà denominata ItemConverterParameters che è una matrice di oggetti.