web-dev-qa-db-ja.com

オブジェクトを属性コンストラクターに渡す方法

次のようにオブジェクトをAttributesコンストラクターに渡そうとしています。

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

この属性コンストラクターでは:

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

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

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

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

55
theringostarrs

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

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)]

つまり、PropertyValidation ctorはTypeを取り、Activator.CreateInstanceコード内でオブジェクトを作成します。理想的には、内部的に文字列を保存するだけであることに注意してください(AssemblyQualifiedName)。

ECMA 334v4から:

§24.1.3属性パラメーターのタイプ

属性クラスの位置パラメータおよび名前付きパラメータのタイプは、属性パラメータタイプに制限されています。

  • 次のタイプのいずれか:boolbytechardoublefloatintlongshortstring
  • タイプobject
  • タイプ System.Type
  • 列挙型。パブリックアクセシビリティがあり、入れ子になっている型(存在する場合)にもパブリックアクセシビリティがあります。
  • 上記のタイプの1次元配列。

そして

§24.2属性の仕様

...

Eは、次のすべてのステートメントが真である場合、属性引数式です。

  • Eのタイプは、属性パラメータータイプです(§24.1.3)。
  • コンパイル時に、Eの値は次のいずれかに解決できます。
    • 定数値。
    • 非ジェネリック型、閉じた構築型(§25.5.2)、またはバインドされていないジェネリック型(§25.5)を指定する式の型(§14.5.11)。
    • Attribute-argument-expressionsの1次元配列。
69
Marc Gravell

以前の投稿者が述べたように、属性引数で使用する型は非常に厳しく制限されています(当然、値を直接アセンブリメタデータBLOBにシリアル化する必要があるため)。

そうは言っても、canを使用できるので、おそらくtypeofsを利用するソリューションを作成できます。

例えば ​​:

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

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

10
Oleg Lvovitch

また...(マイクロソフトのバグだと思います)

デフォルト値を「null」に設定することはできませんが、デフォルトの単純なデフォルト値はOKです(「false」、「7」、「「テスト」)。

NExtの例では、次のエラーが発生します。属性引数は、定数式、typeof式、または属性パラメーター型の配列作成式でなければなりません
ファイル:...\CSC

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

[Sample]
public class Toto
{

}
5
Eric Ouellet