【问题标题】:FluentValidation validation factory and Ninject DI containerFluentValidation 验证工厂和 Ninject DI 容器
【发布时间】:2012-01-25 13:15:10
【问题描述】:

我正在使用NinjectHttpApplication,并在我的项目中定义了几个模块。

我想要的是创建FluentValidation 验证工厂,如http://www.thekip.nl/2011/09/22/using-fluentvalidation-for-both-domain-validation-and-validation-in-mvc-projects/ 中所述。

要创建一个具体的验证工厂,我需要重写

IValidator CreateInstance(Type validatorType) 

我应该调用的方法

return kernel.Get<validatorType>() as IValidator

但我读过不建议在Global.asax 范围之外使用 IKernel。

有哪些选择可以满足我的需求?

编辑:使用 Ninject-FluentValidation 扩展

正如 Remo 所说,GitHub (https://github.com/ninject/ninject.web.mvc.fluentvalidation) 上有一个扩展名。扩展中有一个类:

public class NinjectValidatorFactory : ValidatorFactoryBase { ... }

在构造函数中采用IKernel 并创建IValidator 的实例

public override IValidator CreateInstance(Type validatorType)
{
    if(((IList<IBinding>)Kernel.GetBindings(validatorType)).Count == 0)
    {
        return null;
    }

    return Kernel.Get(validatorType) as IValidator;
}

然后我的代码如下:

public class MvcApplication : NinjectHttpApplication
{
    private NinjectValidatorFactory nvfactory;

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());                        
    }
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Employee", action = "Index", id = UrlParameter.Optional }
        );
    }        
    protected override void OnApplicationStarted()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);

        ModelValidatorProviders.Providers.Clear();
        ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(nvfactory));            
    }
    protected override IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());            
        nvfactory = new NinjectValidatorFactory(kernel);

        return kernel;
    }
}

这行得通。我不知道它是否可以更好地解决。另外我不明白有必要将IKernel 公开为NinjectValidationFactory 上的公共财产。

【问题讨论】:

    标签: c# dependency-injection ninject fluentvalidation


    【解决方案1】:

    Ninject.Web.Mvc.FluentValidation 扩展增加了对 Ninject 流畅验证的支持。它可以在 NuGet 上找到。见https://github.com/ninject/ninject.web.mvc.fluentvalidation

    【讨论】:

    • 如何配置? Github 自述文件并不是特别有用。
    【解决方案2】:

    强烈建议阅读 Mark Seemann 的 Dependency Injection in .NET 书。

    为简单起见,如果您希望向容器询问依赖项,则您没有使用依赖注入。你不调用容器。它会打电话给你。

    【讨论】:

      【解决方案3】:

      这很简单。我向您展示了一个简单的控制台应用程序来演示使用 NInject 进行 FluentValidation。

      1. 在 Visual Studio 中创建控制台应用程序。
      2. 安装所有 nuget 包 FluentValidation 和 NInject。

      Install-Package NInject

      Install-Package FluentValidation

      1. 创建以下类。

        public class Customer
        {
            public int Id { get; set; }
            public string Surname { get; set; }
            public string Forename { get; set; }
            public decimal Discount { get; set; }
            public string Address { get; set; }
        }
        
        using FluentValidation;
        public class CustomerValidator : AbstractValidator<Customer>
        {
            public CustomerValidator()
            {
                //RuleFor(customer => customer.Surname).NotNull();
                RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
            }
        }
        
        using FluentValidation;
        using Ninject;
        using System;
        
        public class NInjectValidatorFactory : ValidatorFactoryBase
        {
            private readonly IKernel m_NInjectKernel;
            public NInjectValidatorFactory(IKernel kernel)
            {
                if (kernel == null)
                    throw new ArgumentNullException("NInject kernel injected is null!!");
        
                m_NInjectKernel = kernel;
            }
            public override IValidator CreateInstance(Type validatorType)
            {
                return m_NInjectKernel.Get(validatorType) as IValidator;
            }
        }
        

        4.程序类里面的main方法如下。

        using FluentValidation;
        using Ninject;
        using System;
        using System.Linq;
        
        class Program
        {
            static void Main(string[] args)
            {
                // Set up the DI Container.
                var kernel = new StandardKernel();
                kernel.Bind<IValidator<Customer>>().To<CustomerValidator>().InSingletonScope();
        
                var nInjectvalidationFactory = kernel.Get<NInjectValidatorFactory>();
                var customer = kernel.Get<Customer>();
        
                var customerValidator = nInjectvalidationFactory.GetValidator<Customer>();
        
                var results = customerValidator.Validate(customer);
        
                if (!results.IsValid)
                    results.Errors.ToList().ForEach(e =>
                    {
                        Console.WriteLine(e.ErrorMessage);
                        Console.WriteLine(e.ErrorCode);
                        Console.WriteLine(e.PropertyName);
                        Console.WriteLine(e.ResourceName);
                        Console.WriteLine(e.Severity);
                    }
                    );
                Console.ReadLine();
            }
        }
        
        1. 运行这个。该代码非常不言自明。在 main 方法中,我们设置了 DI 容器,在本例中为 NInject。然后我们正在做必要的绑定(映射)。注意只需要一个映射。正如here 所解释的那样,这也是一个单例。

      【讨论】:

        【解决方案4】:

        根据您的内核实现,这不是问题。

        不建议这样做,因为它会创建对内核的依赖项(因此您使用的是服务定位而不是依赖注入)。

        另一种选择是使用 Alexsander Beletsky 所述的 Ninjects 提供者概念。

        【讨论】:

        • 好的!那是一篇好文章,但你能解释一下我是如何在我的问题中应用这种方法的吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-21
        相关资源
        最近更新 更多