但是,我找不到实际将其集成到Web应用程序中的任何扩展(例如类似于Ninject.Web.Common)
查看旧的ASP.NET MVC解决方案中的代码,我意识到整个机制是不同的,因为经典的机制依赖于Web核心中不再可用的WebActivatorEx.PreApplicationStartMethod和WebActivatorEx.ApplicationShutdownMethodAttribute.
此外,旧的Ninject.Web.Common程序集提供了几个用于初始化的有用类–Bootstrapper,OnePerRequestHttpModule,NinjectHttpModule:
public static void Start() { DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); Bootstrapper.Initialize(CreateKernel); }
问题:有没有关于如何将Ninject集成到ASP.NET Core 2.0 Web应用程序中的示例?
解决方法
检查this project.但是,它依赖于仍然处于测试版的Ninject 4.0.0,它似乎远不是最终版本(source).对于Ninject 3.3.x,请看下面.
答案很长:
感谢@Steven,我设法创建了一个ASP.NET Core 2.0和Ninject(3.3.x和4.0)的工作解决方案.代码主要来自Missing-Core-DI-Extensions Git repo,非常感谢dotnetjunkie.
无论引用的Ninject版本如何,都必须执行以下操作:
1)在项目中包含AspNetCoreExtensions.cs和AspNetCoreMvcExtensions.cs.
2)创建一个非常简单的服务来用于测试DI:实现ITestService的TestService:
public class TestService : ITestService { public int Data { get; private set; } public TestService() { Data = 42; } } public interface ITestService { int Data { get; } }
如下所示更改Startup.cs:
1)添加这些成员
private readonly AsyncLocal<Scope> scopeProvider = new AsyncLocal<Scope>(); private IKernel Kernel { get; set; } private object Resolve(Type type) => Kernel.Get(type); private object RequestScope(IContext context) => scopeProvider.Value;
2)添加到ConfigureServices(IServiceCollection服务)(最后)
services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>(); services.AddRequestScopingMiddleware(() => scopeProvider.Value = new Scope()); services.AddCustomControllerActivation(Resolve); services.AddCustomViewComponentActivation(Resolve);
3)添加到配置(IApplicationBuilder应用程序,IHostingEnvironment环境,ILoggerFactory loggerFactory)(开头)
Kernel = RegisterApplicationComponents(app,loggerFactory);
private IKernel RegisterApplicationComponents(IApplicationBuilder app,ILoggerFactory loggerFactory) { // IKernelConfiguration config = new KernelConfiguration(); Kernel = new StandardKernel(); // Register application services foreach (var ctrlType in app.GetControllerTypes()) { Kernel.Bind(ctrlType).ToSelf().InScope(RequestScope); } Kernel.Bind<ITestService>().To<TestService>().InScope(RequestScope); // Cross-wire required framework services Kernel.BindToMethod(app.GetRequestService<IViewBufferScope>); Kernel.Bind<ILoggerFactory>().ToConstant(loggerFactory); return Kernel; } private sealed class Scope : DisposableObject { }
5)创建BindToMethod扩展方法
public static class BindingHelpers { public static void BindToMethod<T>(this IKernel config,Func<T> method) => config.Bind<T>().ToMethod(c => method()); }
6)通过将自定义服务注入控制器,将断点设置为测试服务构造函数并检查调用堆栈来测试DI.除了提供一个实例,调用堆栈应该点击自定义代码来集成Ninject(例如,ConfigureRequestScoping方法)
在版本4中不推荐使用IKernel,因此应该使用IReadOnlyKernel和IKernelConfiguration类(尽管上面的代码应该可以工作).
1)使用新类(IReadOnlyKernel)
private readonly AsyncLocal<Scope> scopeProvider = new AsyncLocal<Scope>(); private IReadOnlyKernel Kernel { get; set; } private object Resolve(Type type) => Kernel.Get(type); private object RequestScope(IContext context) => scopeProvider.Value;
2)3)是一样的
4)方法略有不同:
private IReadOnlyKernel RegisterApplicationComponents(IApplicationBuilder app,ILoggerFactory loggerFactory) { IKernelConfiguration config = new KernelConfiguration(); // Register application services foreach (var ctrlType in app.GetControllerTypes()) { config.Bind(ctrlType).ToSelf().InScope(RequestScope); } config.Bind<ITestService>().To<TestService>().InScope(RequestScope); // Cross-wire required framework services config.BindToMethod(app.GetRequestService<IViewBufferScope>); config.Bind<ILoggerFactory>().ToConstant(loggerFactory); return config.BuildReadonlyKernel(); }
5)扩展必须使用IKernelConfiguration
public static class BindingHelpers { public static void BindToMethod<T>(this IKernelConfiguration config,Func<T> method) => config.Bind<T>().ToMethod(c => method()); }