【问题标题】:MVC5 and Ninject:Parameterless constructor errorMVC5 和 Ninject:无参数构造函数错误
【发布时间】: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 框架解决它

标签: c# dependency-injection ninject asp.net-mvc-5


【解决方案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。见stackoverflow.com/a/22774893/982237
  • 没有为我做任何事情。我再次尝试了 MVC5 包,但我没有看到它添加了什么或你如何使用它(没有区别)。我不得不求助于 qujck (stackoverflow.com/a/21313049/4826364) 上面提供的示例
【解决方案3】:

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

采取的步骤:

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

(可选)Api 控制器步骤

  1. 安装 Ninject.Web.WebApi 3.3.0(用于 api ApiController
  2. 安装 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
        }        
    }
}

【讨论】:

    猜你喜欢
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多