3

カスタム データ注釈検証属性へのプロパティ インジェクションを実行できません

 public class CustomValidationAttribute : ValidationAttribute 
 {
    public ILogger Logger { get; set; }

    public CustomValidationAttribute(string keyPointer)
    { }

    public override bool IsValid(object value)
    {
        // Implementation here
        return true;
    }
}

今、私の MVC Application_Start メソッドには、次の Autofac 構成があります。

        // Autofac Ioc Container
        var builder = new ContainerBuilder();
        builder.RegisterType<Logger>().As<ILogger>().InstancePerHttpRequest();
        builder.RegisterType<CustomValidationAttribute>()
        .OnActivating(e =>
        {
            e.Instance.Logger = e.Context.Resolve<ILogger>();
        });
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

自動配線機能も試しました:

builder.RegisterType<CustomValidationAttribute>().PropertiesAutowired();

データ注釈の属性のプロパティはコンパイル時に解決され、ランタイム インジェクションの影響を受けないと推測しています。このメソッドは、MVC フィルター属性に対しては正常に機能しますが、データ アノテーション属性に対しては機能しません。

これを機能させるための代替方法について、どんな助けも本当に感謝しています。

4

4 に答える 4

2

あなたの分析は正しいです-Autofacには、フィルター属性に注入するメカニズムがあります[これは、それらを属性としてインスタンス化せず、MVC 3を公開した機能に依存することによって実現されます]。

検証属性に適用できるそのような自然な拡張ポイントはなく、Autofac はそうしようとしません。

于 2012-10-01T04:02:45.023 に答える
2

参考までに、リポジトリを使用していくつかのデータベース作業を行う必要がある ValidationAttribute に問題があり、リポジトリは Entity Framework DbContext を使用していました。

私たちの問題は、DbContext が属性によってキャッシュされていたことです。これにより、含まれているデータが古くなり、検証の結果に影響を与えました!

IsValid メソッド内の Autofac Lifetimescope 宣言内でリポジトリ解決を行うことで修正しました。

using Autofac;

...

public override bool IsValid(object value)
{
    using (var lifetimeScope = MvcApplication.Container.BeginLifetimeScope())
    {
        var repo = lifetimeScope.Resolve<IMyRepo>();

        // Do your validation checks which require the repo here

    } // The repo will be released / disposed here
}

この問題について文書化されたこのソリューションが他のどこにも見つからないため、ここに私のソリューションを追加するだけです-おそらく、他の誰も私ほど愚かではなかったことは明らかです:)

于 2013-07-30T10:26:48.023 に答える
1

最終的に、新しいバリデータといくつかのリフレクションを使用して、データ注釈にプロパティのインスタンスを設定しました。

 public class IocValidator : DataAnnotationsModelValidator<ValidationAttribute>
{
    public IocValidator(ModelMetadata metadata, ControllerContext context,
        ValidationAttribute attribute)
        : base(metadata, context, attribute) { }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        IEnumerable<PropertyInfo> props = 
            from p in Attribute.GetType().GetProperties()
            where p.CanRead 
                && p.CanWrite
                && (p.PropertyType.IsInterface || p.PropertyType.IsAbstract)
            select p;

        foreach (PropertyInfo prop in props)
        {
            var instance = IocHelper.Resolver.GetService(prop.PropertyType);

            if (instance != null)
                prop.SetValue(Attribute, instance, null);
        }

        return base.Validate(container);
    }
}

次にApplication_Start、新しいバリデーターアダプターを次のように登録しました:-

 DataAnnotationsModelValidatorProvider.RegisterDefaultAdapter(typeof(IocValidator));

このアプローチと Validator での IocHelper の依存関係には、明確なパフォーマンスへの影響があります (皮肉なことに、依存性注入コンテナーへの依存関係です)。

どんな考えやより良いアプローチも大歓迎です。

于 2012-10-02T15:19:16.813 に答える