2009-08-05 20 views
54

Ja próbuje przekazać do konstruktora obiektów Atrybuty następująco:Jak przekazać obiektów do konstruktora atrybutu

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

Z tego konstruktora atrybut:

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

Kod nie skompiluje. Jak mogę przekazać obiekt do atrybutu jak wyżej?

EDYCJA: Tak NullOrEmptyValidatorScheme implementuje IValidatorScheme.

Błąd: błąd CS0182: Argument atrybutu musi być wyrażeniem stałym, wyrażeniem typeof lub wyrażeniem tworzenia tablicy typu parametru atrybutu.

+0

Co to jest błąd kompilacji? Czy jesteś pewien, że 'NullOrEmptyValidatorScheme' implementuje' IValidatorScheme'? –

+0

Jako składnia atrybutów, jest to prawidłowy kod, więc musi to być coś o twoich obiektach. –

+2

@ kek444 - nie, to nie jest ... Dodaję sekcję spec do mojej odpowiedzi ... –

Odpowiedz

65

Wartości w atrybuty są ograniczone do typów prostych; na przykład podstawowe stałe (w tym ciągi) i typeof ... nie można użyć new lub innego bardziej złożonego kodu. W skrócie; nie możesz tego zrobić. Można nadać mu typ jednak:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)] 

czyli PropertyValidation konstruktor pobiera Type i używać Activator.CreateInstance wewnątrz kodu do utworzenia obiektu. Zauważ, że najlepiej jest przechowywać wewnętrznie ciąg znaków (AssemblyQualifiedName).

Od 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.

i

§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

Jest to drugie odniesienie do jednej z dozwolonych wartości, która jest wyliczeniem, jednak implementacja nie była trywialna. Czy znasz przykłady implementacji używających enum? – QueueHammer

+0

@QueueHammer '[DefaultValue (AnyEnum.SomeValue)]' powinno wystarczyć; w przeciwnym razie coś takiego jak '[System.Xml.Serialization.XmlElement (Form = System.Xml.Schema.XmlSchemaForm.Qualified)]' –

10

Jak w poprzednich plakaty zauważyć, rodzaje wykorzystania w argumentach atrybutów są dość mocno ograniczone (co zrozumiałe, ponieważ ich wartości muszą być szeregowane bezpośrednio do blob metadanych montażu).

Powiedział, że prawdopodobnie można stworzyć rozwiązanie, które wykorzystuje typeofs, jak te może być użyte.

Na przykład:

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

Składnia ta jest całkowicie legalne. Kod, który odczytuje twoje atrybuty, musisz uzyskać typ walidatora, utworzyć nową instancję walidatora (może nawet zachować pamięć podręczną walidatorów z kluczami typów walicatora, jeśli jest to odpowiednie - jest to dość powszechna technika), a następnie wywołać ją .

+0

Dziękuję za odpowiedź. Dałem Marcowi zaakceptowaną odpowiedź. Ale Twoja sugestia użycia pamięci podręcznej jest pomocna i przewidywał, że zrobi to, aby zapisać z wielu wywołań Activator.CreateInstance. – theringostarrs

5

także ... (myślę, że to jest Microsoft Bug)

Nie można umieścić domyślną wartość "null", ale domyślnie prosty domyślnej wartości są ok ('false', '7', ' "Test").

Następny przykład daje następujący błąd: Argument atrybut musi być stałym wyrażeniem, typeof ekspresji lub tworzenia tablicy wyrażenia typu parametru atrybut
w pliku: ... \ CSC

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

[Sample] 
public class Toto 
{ 

} 
+0

Może być związany: "Atrybuty i parametry parametrów nazwanych/opcjonalnych nie działają" http://stackoverflow.com/q/8189807/276648 – user276648

+0

Do użytkownika 276648, myślę, że masz rację, są one powiązane i rozwiązanie wydaje się być bardziej kompletne . Dzięki ! –

+0

Właściwie z twoją próbką może to być związane z błędem kompilatora (co znaczy, co napisałeś może działać po kompilacji Mono) http://stackoverflow.com/q/8290853 – user276648

Powiązane problemy