2009-08-05 33 views
54

にオブジェクトを渡すためにどのように私は次のように属性のコンストラクタにオブジェクトを渡すしようとしています:この属性コンストラクタで属性コンストラクタ

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

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

コードはコンパイルされません。上記のように属性にオブジェクトを渡すにはどうすればよいですか?

編集:はいNullOrEmptyValidatorSchemeはIValidatorSchemeを実装しています。

エラー:エラーCS0182:属性引数は、定数式、typeof式、または属性パラメータ型の配列作成式でなければなりません。

+0

をコンパイルエラーとは何ですか? 'NullOrEmptyValidatorScheme'が' IValidatorScheme'を実装していることは確かですか? –

+0

属性の構文に関しては、これは有効なコードなので、オブジェクトに関するものでなければなりません。 –

+2

@ kek444 - いいえ...私の返信に仕様のセクションを追加しています... –

答えて

65

属性への値は単純型に制限されています。たとえば、基本的な定数(文字列を含む)とtypeof ... newまたは他のより複雑なコードは使用できません。要するに;あなたはこれをすることはできません。

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)] 

すなわちPropertyValidation ctorのはTypeを取り、オブジェクトを作成するコードの中Activator.CreateInstanceを使用します。あなたはそれをしかしタイプを与えることができます。理想的には、文字列を内部的に格納するだけでよいことに注意してください(AssemblyQualifiedName)。 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.

§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

これは、許可された値の1つを列挙型にする2番目の参照ですが、実装は簡単です。 enumを使用して実装の例を知っていますか? – QueueHammer

+0

@QueueHammer '[DefaultValue(AnyEnum.SomeValue)]'で十分です。それ以外の場合は、 '[System.Xml.Serialization.XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]のようなものです。 –

10

アセンブリメタデータブロブ)。これらの使用することができますように、あなたはおそらく、typeofsを利用したソリューションを作成することができた

。例えば

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

この構文は完全に合法です。バリデータ型を取得する必要のある属性を読み取るコード、バリデーターの新しいインスタンスを作成する(適切な場合は、バリケーター型にキーされたバリデーターのキャッシュを維持することもできます - これはかなり一般的な手法です)、それを呼び出す。また

+0

お返事ありがとうございます。私はMarcに受け入れられた答えを与えました。しかし、キャッシュを使用することのあなたの提案は有用であり、多くのActivator.CreateInstance呼び出しを保存するためにこれを行うことを想定していました。 – theringostarrs

5

...あなたはデフォルト値に「ヌル」を入れますが、単純なデフォルト値をデフォルトすることはできませんされているOK(「偽」、「7」、 '

(私はそれは、Microsoftのバグだと思います) "テスト")。

次の例では、あなたの次のエラーを与える: 属性の引数は、ファイルの属性パラメータの型
の発現または配列生成式のtypeof、定数式でなければなりません。... \ CSC

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

[Sample] 
public class Toto 
{ 

} 
+0

関連性がある可能性があります:「属性と名前付き/オプションのコンストラクタパラメータが機能しません」http://stackoverflow.com/q/8189807/276648 – user276648

+0

user276648に、私はあなたが正しいと思う、彼らは関連しており、 。ありがとう! –

+0

実際にあなたのサンプルでは、​​コンパイラのバグに関連している可能性があります(Monoによってコンパイルされたときにあなたが書いたものが動作する可能性があることを意味します)http://stackoverflow.com/q/8290853 – user276648