MVC5 和 Ninject 依赖注入失败
Dependency Injection fails with MVC5 and Ninject
我试图在控制器中注入几个 classes,但我失败了。
这是我所做的:
- 添加了
Ninject.Web.WebApi.WebHost
和 WebActivatorEx
NuGet 包
- 在
App_Start
下创建了以下 class:
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();
}
}
}
- 创建了我的 classes:
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
}
}
创建了控制器
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 不工作。
我认为您在 RegisterServices
中的注册调用是错误的 - 您不能绑定接口 .ToSelf()
- 您需要将接口绑定到 具体 class 实现它 - 像这样:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
kernel.Bind<IErp>().To<Erp>().InRequestScope();
}
有了这个,你告诉 DI 容器实例化一个 MyContext
class 每当你在你的代码中你期望一个 IMyContext
依赖
我试图在控制器中注入几个 classes,但我失败了。
这是我所做的:
- 添加了
Ninject.Web.WebApi.WebHost
和WebActivatorEx
NuGet 包 - 在
App_Start
下创建了以下 class:
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();
}
}
}
- 创建了我的 classes:
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
}
}
创建了控制器
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 不工作。
我认为您在 RegisterServices
中的注册调用是错误的 - 您不能绑定接口 .ToSelf()
- 您需要将接口绑定到 具体 class 实现它 - 像这样:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
kernel.Bind<IErp>().To<Erp>().InRequestScope();
}
有了这个,你告诉 DI 容器实例化一个 MyContext
class 每当你在你的代码中你期望一个 IMyContext
依赖