2009-08-05 26 views
54

Sto tentando di passare gli oggetti in un costruttore di attributi come segue:Come passare gli oggetti in un costruttore di attributo

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

Con questo costruttore attributo:

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

Il codice non viene compilato. Come posso passare un oggetto in un attributo come sopra?

MODIFICA: Sì NullOrEmptyValidatorScheme implementa IValidatorScheme.

Errore: errore CS0182: un argomento di attributo deve essere un'espressione costante, un'espressione di espressione di tipo o un'espressione di matrice di un tipo di parametro di attributo.

+0

Qual è l'errore di compilazione? Sei sicuro che 'NullOrEmptyValidatorScheme' implementa' IValidatorScheme'? –

+0

Per quanto riguarda la sintassi degli attributi, questo è un codice valido, quindi deve essere qualcosa sui tuoi oggetti. –

+2

@ kek444 - no non lo è ... Sto aggiungendo la sezione specifica alla mia risposta ... –

risposta

65

I valori negli attributi sono limitati ai tipi semplici; ad esempio, costanti di base (comprese le stringhe) e typeof ... non è possibile utilizzare new o un altro codice più complesso. In breve; non puoi farlo Si può dare il tipo però:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)] 

vale a dire il ctor PropertyValidation prende un Type, e utilizzare Activator.CreateInstance all'interno del codice per creare l'oggetto. Nota che dovresti idealmente archiviare la stringa internamente (AssemblyQualifiedName).

Da ECMA 334v4:

§24.1.3 Attribute parameter types

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

  • One of the following types: bool , byte , char , double , float , int , long , short , string .
  • The type object .
  • The type System.Type .
  • An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility.
  • Single-dimensional arrays of the above types.

e

§24.2 Attribute specification

...

An expression E is an attribute-argument-expression if all of the following statements are true:

  • The type of E is an attribute parameter type (§24.1.3).
  • At compile-time, the value of E can be resolved to one of the following:
    • A constant value.
    • A typeof-expression (§14.5.11) specifying a non-generic type, a closed constructed type (§25.5.2), or an unbound generic type (§25.5).
    • A one-dimensional array of attribute-argument-expressions.
+0

Questo è il secondo riferimento a uno dei valori consentiti essendo un enum, tuttavia l'implementazione non è stata banale. Conosci qualche esempio di implementazione usando enum? – QueueHammer

+0

@QueueHammer '[DefaultValue (AnyEnum.SomeValue)]' dovrebbe essere sufficiente; altrimenti, qualcosa come '[System.Xml.Serialization.XmlElement (Form = System.Xml.Schema.XmlSchemaForm.Qualified)]' –

10

Come nelle precedenti notato, i tipi di utilizzare in argomenti attributi sono piuttosto severamente limitato (comprensibilmente, perché i loro valori devono essere serializzato direttamente il blob dei metadati dell'assieme).

Detto questo, probabilmente si può creare una soluzione che utilizza typeofs, come quelli può essere utilizzato.

Per esempio:

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

Questa sintassi è perfettamente legale. Il codice che legge i tuoi attributi devi ottenere il tipo di validatore, creare una nuova istanza del validatore (può anche mantenere una cache di validatori con chiave sui tipi di valicatore, se appropriato - questa è una tecnica abbastanza comune), e quindi invocarla .

+0

Grazie per la risposta. Ho dato a Marc la risposta accettata. Ma il tuo suggerimento di usare una cache è utile, e avevo previsto di farlo per salvare da molte chiamate Activator.CreateInstance. – theringostarrs

5

anche ... (penso che sia un Bug Microsoft)

Non si può mettere un valore predefinito con "null", ma semplice predefinito valore di default sono ok ('false', '7', ' "Test").

prossimo esempio vi darà il seguente errore: Un argomento attributo deve essere un'espressione costante, typeof espressione o la creazione di matrice espressione di un tipo di parametro di attributo
nel file: ... \ CSC

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

[Sample] 
public class Toto 
{ 

} 
+0

potrebbe essere correlato: "Attributi e parametri costruttore nominati/facoltativi non funzionano" http://stackoverflow.com/q/8189807/276648 – user276648

+0

Per user276648, penso che tu abbia ragione, sono correlati e la soluzione sembra essere più completa . Grazie ! –

+0

In realtà con il tuo esempio potrebbe essere correlato a un bug del compilatore (ciò significa che ciò che hai scritto potrebbe funzionare quando compilato da Mono) http://stackoverflow.com/q/8290853 – user276648

Problemi correlati