Est-il possible de créer un attribut pouvant être initialisé avec un nombre variable d'arguments?
Par exemple:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Les attributs prendront un tableau. Cependant, si vous contrôlez l'attribut, vous pouvez également utiliser params
à la place (ce qui est plus agréable pour les consommateurs, IMO):
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(3, 4, 5)]
class MyClass { }
Il se trouve que votre syntaxe pour la création de tableaux est désactivée:
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
Vous pouvez le faire, mais ce n'est pas conforme CLS:
[Assembly: CLSCompliant(true)]
class Foo : Attribute
{
public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}
Spectacles:
Warning 1 Arrays as attribute arguments is not CLS-compliant
Pour une utilisation régulière de la réflexion, il peut être préférable d'avoir plusieurs attributs, c'est-à-dire.
[Foo("abc"), Foo("def")]
Cependant, cela ne fonctionnera pas avec TypeDescriptor
/PropertyDescriptor
, où une seule instance de n'importe quel attribut est prise en charge (que le premier ou le dernier gagne, je ne me souviens pas lequel).
Essayez de déclarer le constructeur comme ceci:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
Ensuite, vous pouvez l'utiliser comme:
[MyCustomAttribute(3, 4, 5)]
Ça devrait aller. D'après les spécifications, section 17.2:
Une expression E est une expression-argument-attribut si toutes les déclarations suivantes sont vraies:
Voici un exemple:
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
{
}
Oui, mais vous devez initialiser le tableau que vous transmettez. Voici un exemple d'un test de ligne dans nos tests unitaires qui teste un nombre variable d'options de ligne de commande;
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
Vous pouvez le faire. Un autre exemple pourrait être:
class MyAttribute: Attribute
{
public MyAttribute(params object[] args)
{
}
}
[MyAttribute("hello", 2, 3.14f)]
class Program
{
static void Main(string[] args)
{
}
}
Pour reprendre la réponse de Marc Gravell, oui, vous pouvez définir un attribut avec des paramètres de tableau mais appliquer un attribut avec un paramètre de tableau n'est pas conforme CLS. Cependant, la simple définition d'un attribut avec une propriété de tableau est parfaitement conforme à CLS.
Ce qui m'a fait comprendre que Json.NET, une bibliothèque compatible CLS, a une classe d'attributs JsonPropertyAttribute avec une propriété nommée ItemConverterParameters qui est un tableau d'objets.