MVC5 和 Ninject:无参数构造函数错误

Posted

技术标签:

【中文标题】MVC5 和 Ninject:无参数构造函数错误【英文标题】:MVC5 and Ninject:Parameterless constructor error 【发布时间】:2014-02-14 06:10:39 【问题描述】:

在 MVC 5 中,我们得到了这个看起来像这样的帐户控制器。

public class AccountController : Controller
        

            public AccountController()
                : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
            

            

            public AccountController(UserManager<ApplicationUser> userManager)
            
                UserManager = userManager;
            
        

我安装了 Ninject 来处理我的依赖注入。我有两个存储库,我想在我的 AccountController 中使用 现在代码看起来像这样

    public class AccountController : Controller
    
              private readonly ILicenserepository _licenserepository;
              private readonly IUserRepository _userRepository;    

        public AccountController(ILicenserepository licenserepository, IUserRepository userRepository)
            : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
        
            _licenserepository = licenserepository;
            _userRepository = userRepository;
        

        public AccountController(UserManager<ApplicationUser> userManager)
        
            UserManager = userManager;
        
    

在 ninject.web.common 这就是我所做的

private static void RegisterServices(IKernel kernel)

    kernel.Bind(typeof (ILicenserepository)).To(typeof (Licenserepository));
    kernel.Bind(typeof (IUserRepository)).To(typeof (UserRepository));
    

但是当我运行应用程序时,我在浏览器上收到错误消息,提示找不到无参数构造函数。如果我创建无参数构造函数,我的存储库不会被实例化。所以无论我从存储库中调用该方法,该值都是空的。 我怎么解决这个问题?或者让 MVC 或 Ninject 知道调用哪个构造函数?

【问题讨论】:

我没有具体的解决方案,但是当使用任何类型的依赖注入时,您需要替换创建控制器的代码。通常你必须实现你自己的(简单的)控制器工厂来注入你需要的依赖。默认工厂将需要无参数构造函数您还可以从 DefaultControllerFactory 扩展(请参阅 msdn:msdn.microsoft.com/en-us/library/…)并在那里解决您的依赖关系。然后将你的新工厂注册到 MVC5 您可以通过ControllerBuilder.SetControllerFactory(链接:msdn.microsoft.com/en-us/library/…)设置新控制器。希望对你有帮助 并且 fwiw:不要在构造函数中创建 UserManager,这会使您的类不支持 UnitTest。将 UserManager 实现为接口并将 IUserManager 作为唯一依赖项传递给类并通过您的 DI 框架解决它 【参考方案1】:

您需要在 Global.asax.cs 中注册的DependencyResolver

注册看起来像这样:

protected void Application_Start()

    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    RegisterDependencyResolver();


private void RegisterDependencyResolver()

    var kernel = new StandardKernel();

    // you may need to configure your container here?
    RegisterServices(kernel);

    DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));

还有DependencyResolver

public class NinjectDependencyResolver : IDependencyResolver

    private readonly IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel)
    
        this.kernel = kernel;
    

    public object GetService(Type serviceType)
    
        return this.kernel.TryGet(serviceType);
    

    public IEnumerable<object> GetServices(Type serviceType)
    
        try
        
            return this.kernel.GetAll(serviceType);
        
        catch (Exception)
        
            return new List<object>();
        
    

【讨论】:

嗯,抱歉,这听起来可能很愚蠢,但通过配置我的容器,您意味着将 Irepository 绑定到存储库,而 RegisterServices 来自哪里? 您不需要推出自己的 DependencyResolver - 它由 Ninject.Mvc3 包提供(它也适用于 MVC4 和 5)。 这就是我的想法,但是在我的 MVC5 项目中添加了 nuget 包之后,我无处可去,直到我不得不做上面 qujck 详述的脚手架。【参考方案2】:

这是一个更新: 如果您使用的是 MVC5 和 WebAPI 2,那么您需要做的就是使用 NuGet 管理器并将 NinjectMVC5 和 NinjectWebApi2 添加到您的项目中。然后错误消失。 (使用 Visual Studio 2013)

干杯

【讨论】:

您将需要来自 nuget 或 OwinHost 包的 Ninject.Web.WebApiNinject.Web.WebApi.WebHost。见***.com/a/22774893/982237 没有为我做任何事情。我再次尝试了 MVC5 包,但我没有看到它添加了什么或你如何使用它(没有区别)。我不得不求助于 qujck (***.com/a/21313049/4826364) 上面提供的示例【参考方案3】:

我刚刚使用 .NET MVC 5 和 Ninject 3.3.4 正常工作。

采取的步骤:

    安装 Ninject 3.3.4 安装 Ninject.Web.Common 3.3.1 安装 Ninject.Web.Common.WebHost 3.3.1 安装 Ninject.MVC5 3.3.0(用于 MVC Controller

(可选)Api 控制器步骤

    安装 Ninject.Web.WebApi 3.3.0(用于 api ApiController) 安装 Ninject.Web.WebApi.WebHost(用于ApiController

这里的重要区别是您的项目是使用 Api 控制器还是 Mvc 控制器。如果您不熟悉其中的区别,请查看以下帖子:

Difference between ApiController and Controller in ASP.NET MVC.

注意:我确实不必对我的 Ninject.Web.Common.cs 文件进行任何额外的配置。下面是我的配置,省略了绑定


[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Stop")]

namespace YourProject.Web.App_Start

    using System;
    using System.Web;
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;
    using Ninject.Web.Common.WebHost;

    public static class NinjectWebCommon 
    
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start() 
        
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        
            bootstrapper.ShutDown();
        

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        
            var kernel = new StandardKernel();
            try
            
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
                RegisterServices(kernel);
                return kernel;
            
            catch
            
                kernel.Dispose();
                throw;
            
        

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        
            // Common

            // Repositories

            // Services

            // Factories

            // Misc
                
    


【讨论】:

以上是关于MVC5 和 Ninject:无参数构造函数错误的主要内容,如果未能解决你的问题,请参考以下文章

没有为此对象定义无参数构造函数。 MVC 5

构造函数 析构函数

在构造函数中使用带有附加参数的 Ninject 创建实例

(笔记):构造函数与析构函数

C++再识类和对象

9. 构造函数和析构函数