【问题标题】:Dependency Injection fails with MVC5 and NinjectMVC5 和 Ninject 的依赖注入失败
【发布时间】:2017-12-09 00:32:14
【问题描述】:

我试图在控制器中注入几个类,但我失败了。

这就是我所做的:

  1. 添加了Ninject.Web.WebApi.WebHostWebActivatorEx NuGet 包
  2. App_Start下创建了以下类:

NinjectWebCommon.cs

using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
using MyProject;
using MyProject.Models;
using MyProject.Classes;
using System;
using System.Web;

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

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

        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IMyContext>().ToSelf().InRequestScope();
            kernel.Bind<IErp>().ToSelf().InRequestScope();
        }
    }
}
  1. 创建了我的课程:

MyContext.cs:

using MyProject.Models;
using System;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Threading.Tasks;

namespace MyProject.Models
{
    public interface IMyContext : IDisposable
    {
        DbSet<Operator> Operators { get; set; }
        Task<int> SaveChangesAsync();
    }

    public class MyContext : DbContext, IMyContext
    {
        public MyContext () : base("MyContext ") { }
        public DbSet<Operator> Operators { get; set; }
        public async override Task<int> SaveChangesAsync()
        {
            return await SaveChangesAsync(CancellationToken.None);
        }
    }
}

Erp.cs

public interface IErp
{
    Task ImportListAsync();
}

public class Erp : IErp
{
    private readonly IMyContext _context;
    public Erp(IMyContext context)
    {
        _context = context;
    }

    public async Task ImportListAsync()
    {
        // do something
    }
}
  1. 创建了一个控制器

    using MyProject.Classes;
    using MyProject.Models;
    using System.Data.Entity;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    
    namespace MyProject.Controllers
    {
        public class OperatorsController : Controller
        {
            private readonly IMyContext _context;
            private readonly IErp _erp;
    
            public OperatorsController(IMyContext context, Erp Ierp)
            {
                _context = context;
                _erp = erp;
            }
    
            // GET: Operators
            public async Task<ActionResult> Index()
            {
                return View(await _context.Operators.ToListAsync());
            }
    
            // GET: Operators/Import
            public async Task<ActionResult> Import()
            {
                await _erp.ImportListAsync();
                return View("Index", await _context.Operators.ToListAsync());
            }
        }
    }
    

但是当我运行应用程序时,我仍然收到关于缺少无参数构造函数的臭名昭著的错误。这告诉我 DI 不起作用。

【问题讨论】:

  • 顺便说一句,我无法修复最后一个代码 sn-p 的格式。
  • 如果您使用 MVC,为什么要使用 Web API 包?为什么不使用 MVC 包?
  • 我在创建新项目时选择了一个单页应用程序,这就是它创建的模板。
  • 那么您的建议是什么?避免使用 MVC 模板创建 SPA 并从头开始?
  • 没有。我是说为您选择的框架使用适当的集成包。如果您正在使用 MVC,请使用 MVC 包。如果您正在使用 Web API,请使用 Web API 包。如果您同时使用它们,请同时使用它们。

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


【解决方案1】:

我相信您在 RegisterServices 中的注册调用是错误的 - 您无法绑定接口 .ToSelf() - 您需要将接口绑定到实现它的 具体类 - 如下所示:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
    kernel.Bind<IErp>().To<Erp>().InRequestScope();
}

有了这个,你告诉 DI 容器实例化一个 MyContext 类,只要在你的代码中你期望一个 IMyContext 依赖项

【讨论】:

    猜你喜欢
    • 2015-10-20
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2019-02-17
    • 2012-08-13
    • 2017-09-24
    相关资源
    最近更新 更多