web-dev-qa-db-fra.com

Comment passer des objets dans un constructeur d'attributs

J'essaie de passer des objets dans un constructeur d'attributs comme suit:

[PropertyValidation(new NullOrEmptyValidatorScheme())]
public string Name { get; private set; }

Avec ce constructeur d'attribut:

 public PropertyValidationAttribute(IValidatorScheme validator) {
      this._ValidatorScheme = validator;
    }

Le code ne se compilera pas. Comment puis-je passer un objet dans un attribut comme ci-dessus?

EDIT: Oui NullOrEmptyValidatorScheme implémente IValidatorScheme.

L'erreur: erreur CS0182: Un argument d'attribut doit être une expression constante, une expression de typeof ou une expression de création de tableau d'un type de paramètre d'attribut.

55
theringostarrs

Les valeurs en attributs sont limitées à des types simples; par exemple, les constantes de base (y compris les chaînes) et typeof... vous ne pouvez pas utiliser new ou un autre code plus complexe. En bref; tu ne peux pas faire ça. Vous pouvez lui donner le type cependant:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)]

c'est-à-dire que le PropertyValidation ctor prend un Type, et utilise Activator.CreateInstance à l'intérieur du code pour créer l'objet. Notez que vous devriez idéalement simplement stocker la chaîne en interne (AssemblyQualifiedName).

De l'ECMA 334v4:

§24.1.3 Types de paramètres d'attribut

Les types de paramètres positionnels et nommés pour une classe d'attributs sont limités aux types de paramètres d'attribut , qui sont:

  • L'un des types suivants: bool, byte, char, double, float, int, long, short, string.
  • Le type object.
  • Le type System.Type.
  • Un type enum, à condition qu'il ait une accessibilité publique et que les types dans lesquels il est imbriqué (le cas échéant) aient également une accessibilité publique.
  • Tableaux unidimensionnels des types ci-dessus.

et

§24.2 Spécification d'attribut

...

Une expression E est une expression-argument-expression si toutes les instructions suivantes sont vraies:

  • Le type de E est un type de paramètre d'attribut (§24.1.3).
  • Au moment de la compilation, la valeur de E peut être résolue comme suit:
    • Une valeur constante.
    • Typeof-expression (§14.5.11) spécifiant un type non générique, un type construit fermé (§25.5.2) ou un type générique non lié (§25.5).
    • Un tableau unidimensionnel d'expressions d'argument d'attribut.
69
Marc Gravell

Comme indiqué dans les affiches précédentes, les types utilisés dans les arguments d'attribut sont très sévèrement restreints (naturellement, car leurs valeurs doivent être sérialisées directement dans le blob de métadonnées Assembly).

Cela dit, vous pouvez probablement créer une solution qui utilise typeofs , car ces peuvent être utilisés.

Par exemple :

[PropertyValidation(typeof(NullOrEmptyValidatorScheme))]
public string Name { get; private set; }

Cette syntaxe est parfaitement légale. Le code qui lit vos attributs, vous devez obtenir le type de validateur, créer une nouvelle instance du validateur (il peut même maintenir un cache de validateurs basés sur des types de validateurs, le cas échéant - c'est une technique assez courante), puis l'invoquer .

10
Oleg Lvovitch

Aussi ... (je pense que c'est un bug Microsoft)

Vous ne pouvez pas mettre une valeur par défaut à "null" mais la valeur par défaut simple par défaut est ok ('false', '7', '"Test").

L'exemple NExt vous donnera l'erreur suivante: Un argument d'attribut doit être une expression constante, une expression de typeof ou une expression de création de tableau d'un type de paramètre d'attribut
dans le fichier: ...\CSC

public class SampleAttribute : Attribute
{
    private string _test;
    public SampleAttribute(string test = null)
    {
        _test = test;
    }
}

[Sample]
public class Toto
{

}
5
Eric Ouellet