简短回答:
check 这个项目 https://github.com/dotnetjunkie/Missing-Core-DI-Extensions/blob/master/src/SampleApplication.Ninject/Startup.cs。然而,它依赖于 Ninject 4.0.0,该版本仍处于测试版本,似乎距离最终版本还很远(source https://stackoverflow.com/questions/38261521/ninject-in-net-core/46521359#46521359)。对于 Ninject 3.3.x,请参见下文。
长答案:
谢谢@Steven
我成功创建了 ASP.NET Core 2.0 和 Ninject(3.3.x 和 4.0)的工作解决方案。代码主要来自缺少核心 DI 扩展 https://github.com/dotnetjunkie/Missing-Core-DI-Extensions/blob/master/src/SampleApplication.Ninject/Startup.csGit 存储库,非常感谢点网迷 https://github.com/dotnetjunkie.
无论引用的 Ninject 版本如何,都必须执行以下操作:
1) 包括AspNetCore 扩展.cs https://github.com/dotnetjunkie/Missing-Core-DI-Extensions/blob/master/src/MissingDIExtensions/AspNetCoreExtensions.cs and AspNetCoreMvcExtensions.cs https://github.com/dotnetjunkie/Missing-Core-DI-Extensions/blob/master/src/MissingDIExtensions/AspNetCoreMvcExtensions.cs在你的项目中。
2) 创建一个非常简单的服务用于测试 DI:TestService
实现ITestService
:
public class TestService : ITestService
{
public int Data { get; private set; }
public TestService()
{
Data = 42;
}
}
public interface ITestService
{
int Data { get; }
}
忍者3.3.x https://www.nuget.org/packages/Ninject/4.0.0-beta-0134
Change 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)
(在最后)
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddRequestScopingMiddleware(() => scopeProvider.Value = new Scope());
services.AddCustomControllerActivation(Resolve);
services.AddCustomViewComponentActivation(Resolve);
3)添加到Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
(在开头)
Kernel = RegisterApplicationComponents(app, loggerFactory);
4)添加以下方法和内部类:
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
method)
忍者4.0.0 https://www.nuget.org/packages/Ninject/4.0.0-beta-0134
IKernel
已在版本 4 中弃用,因此应使用 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());
}