【问题标题】:Database injection into a validation attribute with ASP MVC and Castle Windsor使用 ASP MVC 和 Castle Windsor 将数据库注入验证属性
【发布时间】:2009-06-12 10:29:04
【问题描述】:

我需要一些帮助 - 我正在尝试在需要进行数据库调用的 ASP.NET MVC Web 项目中使用自定义验证属性。

我已经成功地为控制器工作了 Windsor,并且 IRepository 接口被正常注入。当我需要将存储库注入属性类时,问题就出现了。

属性类代码如下:

public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
    private readonly string message;
    private readonly IArticleRepository articleRepository;

    public ValidateUniqueUrlNodeAttribute(string message)
    {
        this.message = message;
    }

    public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
    {
        this.articleRepository = articleRepository;
    }
    public override IValidator Build()
    {
        var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };

        ConfigureValidatorMessage(validator);

        return validator;
    }

我的问题是我似乎无法让 Windsor 拦截要传入 IArticleRepository 的属性构造

我的 global.asax 文件中的当前代码如下:

container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
   container
     .RegisterControllers(Assembly.GetExecutingAssembly())
     .AddComponent<IArticleRepository, ArticleRepository>()
     .AddComponent<ValidateUniqueUrlNodeAttribute>();

任何帮助将不胜感激。

【问题讨论】:

    标签: c# asp.net-mvc castle-windsor


    【解决方案1】:

    AFAIK 没有依赖注入容器可以直接管理一个属性,因为它是由运行时实例化的,没有办法拦截它。

    但是,他们可以通过以下方式作弊

    1. 使用容器的静态网关 (example),或
    2. 使用“BuildUp”功能注入在已构建对象中找到的任何依赖项。这称为BuildUp in UnityInjectProperties in Autofac

    Windsor 不支持 #2(ref1ref2),因此您可以:

    1. 尝试其中一种技巧来使 Windsor 支持 #2(hack1hack2
    2. 使用static gateway
    3. 实现您自己的 IValidatorBuilder 并使其使用 Windsor 创建验证器。我确定这是在某个地方实现的,但我现在找不到它......

    【讨论】:

      【解决方案2】:

      不知道这是否有帮助,但我将ValidationAttribute 子类化为公开Resolve&lt;T&gt;() 方法,如下所示:

      public abstract class IocValidationAttribute : ValidationAttribute
      {
          protected T Resolve<T>()
          {
              return IocHelper.Container().Resolve<T>();
          }
      }
      

      然后可以在任何需要命中数据库的自定义ValidatorAttribute中使用:

      public class UniqueEmailAttribute : IocValidationAttribute
      {
          public override bool IsValid(object value)
          {
              ICustomerRepository customerRepository = Resolve<ICustomerRepository>();
      
              return customerRepository.FindByEmail(value.ToString()) == null;
          }
      }
      

      我认为这是 Mauricio Scheffer 提到的“静态网关”方法的一种变体。我不知道这是不是一个好的设计。我不是它的忠实拥护者,我宁愿将依赖项注入得更“优雅”,尽管我显然不能使用构造函数注入,但我想使用属性注入但无法找到解决方法挂钩到 ASP.NET MVC 框架代码来执行此操作(我什至仔细研究过 MVC2 源代码)。

      【讨论】:

      • 你从哪里获得 IocHelper?
      • @soniic 看起来像一个邪恶的静电
      【解决方案3】:

      我能够将它连接起来 [碰巧使用 Autofac,但它只是通过 ASP.NET MVC DependencyResolver] in this answer 进行构造函数注入,从而可以编写:

      class MyModel 
      {
          ...
          [Required, StringLength(42)]
          [ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
          public string MyProperty { get; set; }
          ....
      }
      
      public class MyDiDependentValidator : Validator<MyModel>
      {
          readonly IUnitOfWork _iLoveWrappingStuff;
      
          public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
          {
              _iLoveWrappingStuff = iLoveWrappingStuff;
          }
      
          protected override bool IsValid(MyModel instance, object value)
          {
              var attempted = (string)value;
              return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
          }
      }
      

      使用一些辅助类(看那里),你可以把它连接起来,例如在 ASP.NET MVC 中就像在 Global.asax 中一样:-

      DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
          typeof(ValidatorServiceAttribute),
          (metadata, context, attribute) =>
              new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
      

      【讨论】:

        【解决方案4】:

        嗯。

        您能否测试删除(字符串消息)ctor 的效果,看看这是否至少迫使 Castle 将 ctor 与 Repostiory 一起使用?

        否则我们调用 AddComponent(name, type, type)。除此之外它真的应该工作......

        这是否也暗示了我的第一个想法? How do I use Windsor to inject dependencies into ActionFilterAttributes

        【讨论】:

        • 抱歉,我无法删除字符串 CTOR,因为属性如下所示: [ValidateUniqueUrlNode("请输入唯一的 Url")] public string UrlNode { get;放;这应该不同吗?
        • 呵呵。还在摸不着头脑……我去搜一下
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 2011-08-17
        相关资源
        最近更新 更多