ASP.NET MVCでは、データアノテーション属性(具体的には、検証属性を使用しています)でコンストラクターインジェクションを使用できますか?
私がしたいことは次のとおりです。
public class NoEmailTakenAttribute : ValidationAttribute
{
public NoEmailTakenAttribute(IService service) { .. }
}
それは可能ですか?
ありがとう。
ASP.NET MVCでは、データアノテーション属性(具体的には、検証属性を使用しています)でコンストラクターインジェクションを使用できますか?
私がしたいことは次のとおりです。
public class NoEmailTakenAttribute : ValidationAttribute
{
public NoEmailTakenAttribute(IService service) { .. }
}
それは可能ですか?
ありがとう。
Reflector を使用して見たところ、Controller インジェクションは使用できませんが、プロパティ インジェクションは使用できるようです。から継承するクラスを作成しDataAnnotationsModelValidatorProvider
、メソッドをオーバーライドするGetValidators
ことにより、検証が行われる前に属性をプロパティに注入できる可能性がありそうです...これは初期分析によるものであり、まだ完全には決定されていません。
BrianMainsによって提案されたソリューションは正常に機能するはずです。ここではコンストラクタインジェクションはオプションではないと思いますが、プロパティインジェクションで十分です。から派生することができModelValidatorProvider
、実装はこれに似ているように見えるかもしれません:
public class MyModelValidatorProvider : ModelValidatorProvider
{
private IDiContainer _container;
public MyModelValidatorProvider(IDiContainer container)
{
_container = container;
}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
List<ModelValidator> validators = new List<ModelValidator>();
PropertyInfo targetProperty = metadata.ContainerType.GetProperty(metadata.PropertyName);
if (targetProperty.GetCustomAttributes(false).Any(attr => attr.GetType() == typeof(NoEmailTakenAttribute)))
{
DataAnnotationsModelValidator<NoEmailTakenAttribute> validator = new DataAnnotationsModelValidator<NoEmailTakenAttribute>(
metadata, context, _container.Resolve<NoEmailTakenAttribute>());
validators.Add(validator);
}
return validators;
}
}
私は詳細に調べModelMetadata
ず、バリデーターを返すかどうかを決定するために反射を使用しましたが、おそらくもっとうまくいく可能性があります。
次にGlobal.asax
、以下を追加します。
ModelValidatorProviders.Providers.Add(new MyModelValidatorProvider(InstanceOfContainer));
そして、あなたは行ってもいいはずです。ここでの唯一の問題は、バリデーターがデフォルトのメカニズムによっても作成されることです。明らかに、これにより、バリデーターに適切な依存関係が注入されなくなります。バリデーターをデフォルトの作成から除外する方法はわかりませんが、バリデーター内のnull値を適切にチェックすれば、正常に機能するはずです(少し回避策を説明する必要がありますが、より良い方法が見つかるかもしれません)。
これを行うには、基本コントローラー クラスを作成し、IService インターフェイスのプロパティを宣言し、パラメーター IService を使用して基本コントローラー クラスを記述します。これを派生クラスで使用します。asp.net mvc はデフォルトのコントローラー コンストラクターを使用して、サービスが派生クラスのパラメーター化されたコンストラクターによってインスタンス化される時間を初期化します。
カスタム データ注釈のコンストラクター注入やプロパティ注入を行う簡単な方法はないと思います。@BrianMains が提案したことはもっともらしく聞こえますが、私自身はそこまで行っていません。
複雑さを回避する 1 つの方法は、カスタム データ アノテーションでサービス ロケーターを使用して、必要な依存関係を取得することです。きれいではありませんが、同じ結果が得られます。
詳細については、このリンクを確認してください: ASP.Net MVC 3 のカスタム DataAnnotations での依存性注入