Ninject 使用 Web Api、SignalR、MVC 和 OWIN
Ninject with Web Api, SignalR, MVC and OWIN
我在我的 Web 应用程序中使用 Ninject DI,其中包含来自 Asp.Net 堆栈(MVC、Web Api 2、SignalR)的一系列技术。
我已经通过以下方法使 DI 适用于所有正在使用的技术:
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>
internal 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;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding services here
}
}
到目前为止一切顺利。
所有这一切都与 Web Api 一起工作,正在 Global.asax 中初始化。
现在我要切换到 OWIN 管道。所以我从 Global.asax 中删除了 GlobalConfiguration.Configure(WebApiConfig.Register);
并添加了
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
给我的 OwinStartup
class。 Web DI Api 停止工作。
我开始寻找合适的解决方案并找到了 Ninject.Web.WebApi.OwinHost
包。因此,为了让单个内核解决所有技术的依赖关系,我进行了以下更改:
在 OwinStartup 中:
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
在 NinjectWebCommon:
//[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Start")]
//[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Stop")]
禁用这些行以避免两次初始化内核。
此修复了 Web 的 DI Api 但不是 SignalR。当客户端尝试连接到集线器时,出现以下异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessNegotiationRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(IDictionary`2 environment)
at Microsoft.AspNet.SignalR.Owin.Middleware.HubDispatcherMiddleware.Invoke(IOwinContext context)
at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
at Microsoft.Owin.Mapping.MapMiddleware.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<InvokeCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Ninject.Web.Common.OwinHost.OwinBootstrapper.<Execute>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.<RunApp>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.<DoFinalWork>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar)
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) | RuntimeMethodInfo.UnsafeInvokeInternal => RuntimeMethodHandle.InvokeMethod => Application.Application_Error
我有点迷路了。我已经阅读了大约两打文章,但其中 none 为我提供了解决方案。非常感谢任何帮助。
我的最终目标是拥有一个为 Web Api、MVC 和 SignalR 提供服务并支持 OWIN 管道的内核。
编辑: 因为我有评论说我的案例可能与另一个问题重复,所以我认为我需要给出一些解释。
我有三种情况。
WebApi 使用 GlobalConfiguration.Configure(WebApiConfig.Register)
在 Global.asax 中初始化,Ninject 使用 NinjectWebCommon 和 Bootstrapper 初始化。
这为我提供了 WebApi 和 SignalR 中的注入。但是因为我想将 WebApi 初始化移动到 OWIN 启动,所以这种方法已经过时了。
WebApi 使用 OWIN Startup 初始化,Ninject 使用 NinjectWebCommon 和 Bootstrapper 初始化。
SignalR 注入有效,WebApi 注入无效。
WebApi 使用 OWIN Startup 初始化,Ninject 使用 UseNinjectMiddleware 初始化,UseNinjectWebApi.
WebApi 注入有效,SignalR 注入无效。
所以基本上我需要弄清楚如何将它们放在一起,以便当我在 OWIN 管道上初始化 WebApi 时 WebApi 和 SignalR 注入都能正常工作。
NinjectWebCommon 的代码在下面的原始问题中。它包含用于创建 SignalR 解析器的代码,但在场景 3 中没有帮助。
编辑 2: 经过几个小时的反复试验,我得出的结论是调用
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
与此调用冲突:
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
所以问题描述缩小到这个。当我使用以下模式时,SignalR 停止工作:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(config);
GlobalHost.HubPipeline.AddModule(new GlobalSignalRExceptionHandler());
app.MapSignalR();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new Ninject.Web.Mvc.NinjectDependencyResolver(kernel));
return kernel;
}
但是如果我评论这行
//GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
SignalR 再次开始工作。但是当然没有在集线器内注入。
为了对 WebApi 和 SignalR 使用依赖解析器,您需要实现如下所示的 class:
public class NinjectDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver,
System.Web.Http.Dependencies.IDependencyResolver
{
public readonly IKernel Kernel;
public NinjectDependencyResolver(string moduleFilePattern)
: base()
{
Kernel = new StandardKernel();
Kernel.Load(moduleFilePattern);
}
public override object GetService(Type serviceType)
{
var service = Kernel.TryGet(serviceType) ?? base.GetService(serviceType);
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
IEnumerable<object> services = Kernel.GetAll(serviceType).ToList();
if (services.IsEmpty())
{
services = base.GetServices(serviceType) ?? services;
}
return services;
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{ }
}
然后在您的启动程序中 class 您应该为 WebApi 和 SignalR 注册 NinjectDependencyResolver,如下所示:
public void Configuration(IAppBuilder app)
{
var dependencyResolver = new NinjectDependencyResolver("*.dll");
var httpConfiguration = new HttpConfiguration();
httpConfiguration.DependencyResolver = dependencyResolver;
app.UseWebApi(httpConfiguration);
var hubConfig = new HubConfiguration { Resolver = dependencyResolver };
app.MapSignalR(hubConfig);
}
最后,我设法获得了支持 OWIN 管道、WebApi、MVC 和 SignalR 的工作 Ninject 配置。
当我发布问题时,我有一个解决方法(在 SignalR 集线器中禁用 DI)所以我决定不再浪费时间在这上面并继续前进。
但是当我尝试 运行 OWIN 内存中测试服务器与我的启动 class 时,发现 DI 不工作。 CreateKernel 方法调用得太晚,导致创建了一个在 sengleton 范围内使用的对象的多个实例。
在尝试了不同的初始化变体之后,我让 DI 可以用于 OWIN 测试服务器,它还修复了 SignalR DependencyResolver。
解决方法:
我停止使用包 Ninject.Web.Common.OwinHost 和 Ninject.Web.WebApi.OwinHost 因此这些调用已从我的配置方法中删除:
//app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
//app.UseNinjectWebApi(config);
我改为执行以下操作:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
NinjectWebCommon.Start();
config.DependencyResolver = new NinjectDependencyResolver(NinjectWebCommon.bootstrapper.Kernel);
app.UseWebApi(config);
app.MapSignalR();
}
public static class NinjectWebCommon
{
private static bool _isStarted;
internal static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
// When creating OWIN TestService instances during unit tests
// Start() method might be called several times
// This check ensures that Ninject kernel is initialized only once per process
if (_isStarted)
return;
_isStarted = true;
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
internal static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// DI for SignalR
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
// DI for MVC
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding code here
kernel.Bind<Something>().ToSelf().InSingletonScope();
}
}
必须在依赖注入配置之后配置 SignalR。因此,在您的 OWIN 启动 class 中,确保 app.MapSignalR()
在 之后被调用 设置 MVC 依赖解析器(System.Web.MVC.DependencyResolver
),WebApi 依赖解析器(System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver
) 和 SignalR 依赖解析器 (Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver
)。
我在我的 Web 应用程序中使用 Ninject DI,其中包含来自 Asp.Net 堆栈(MVC、Web Api 2、SignalR)的一系列技术。
我已经通过以下方法使 DI 适用于所有正在使用的技术:
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>
internal 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;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding services here
}
}
到目前为止一切顺利。
所有这一切都与 Web Api 一起工作,正在 Global.asax 中初始化。
现在我要切换到 OWIN 管道。所以我从 Global.asax 中删除了 GlobalConfiguration.Configure(WebApiConfig.Register);
并添加了
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
给我的 OwinStartup
class。 Web DI Api 停止工作。
我开始寻找合适的解决方案并找到了 Ninject.Web.WebApi.OwinHost
包。因此,为了让单个内核解决所有技术的依赖关系,我进行了以下更改:
在 OwinStartup 中:
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
在 NinjectWebCommon:
//[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Start")]
//[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Stop")]
禁用这些行以避免两次初始化内核。
此修复了 Web 的 DI Api 但不是 SignalR。当客户端尝试连接到集线器时,出现以下异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessNegotiationRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(IDictionary`2 environment)
at Microsoft.AspNet.SignalR.Owin.Middleware.HubDispatcherMiddleware.Invoke(IOwinContext context)
at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
at Microsoft.Owin.Mapping.MapMiddleware.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<InvokeCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Ninject.Web.Common.OwinHost.OwinBootstrapper.<Execute>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.<RunApp>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.<DoFinalWork>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar)
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) | RuntimeMethodInfo.UnsafeInvokeInternal => RuntimeMethodHandle.InvokeMethod => Application.Application_Error
我有点迷路了。我已经阅读了大约两打文章,但其中 none 为我提供了解决方案。非常感谢任何帮助。
我的最终目标是拥有一个为 Web Api、MVC 和 SignalR 提供服务并支持 OWIN 管道的内核。
编辑: 因为我有评论说我的案例可能与另一个问题重复,所以我认为我需要给出一些解释。
我有三种情况。
WebApi 使用
GlobalConfiguration.Configure(WebApiConfig.Register)
在 Global.asax 中初始化,Ninject 使用 NinjectWebCommon 和 Bootstrapper 初始化。这为我提供了 WebApi 和 SignalR 中的注入。但是因为我想将 WebApi 初始化移动到 OWIN 启动,所以这种方法已经过时了。
WebApi 使用 OWIN Startup 初始化,Ninject 使用 NinjectWebCommon 和 Bootstrapper 初始化。
SignalR 注入有效,WebApi 注入无效。
WebApi 使用 OWIN Startup 初始化,Ninject 使用 UseNinjectMiddleware 初始化,UseNinjectWebApi.
WebApi 注入有效,SignalR 注入无效。
所以基本上我需要弄清楚如何将它们放在一起,以便当我在 OWIN 管道上初始化 WebApi 时 WebApi 和 SignalR 注入都能正常工作。
NinjectWebCommon 的代码在下面的原始问题中。它包含用于创建 SignalR 解析器的代码,但在场景 3 中没有帮助。
编辑 2: 经过几个小时的反复试验,我得出的结论是调用
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
与此调用冲突:
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
所以问题描述缩小到这个。当我使用以下模式时,SignalR 停止工作:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(config);
GlobalHost.HubPipeline.AddModule(new GlobalSignalRExceptionHandler());
app.MapSignalR();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new Ninject.Web.Mvc.NinjectDependencyResolver(kernel));
return kernel;
}
但是如果我评论这行
//GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
SignalR 再次开始工作。但是当然没有在集线器内注入。
为了对 WebApi 和 SignalR 使用依赖解析器,您需要实现如下所示的 class:
public class NinjectDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver,
System.Web.Http.Dependencies.IDependencyResolver
{
public readonly IKernel Kernel;
public NinjectDependencyResolver(string moduleFilePattern)
: base()
{
Kernel = new StandardKernel();
Kernel.Load(moduleFilePattern);
}
public override object GetService(Type serviceType)
{
var service = Kernel.TryGet(serviceType) ?? base.GetService(serviceType);
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
IEnumerable<object> services = Kernel.GetAll(serviceType).ToList();
if (services.IsEmpty())
{
services = base.GetServices(serviceType) ?? services;
}
return services;
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{ }
}
然后在您的启动程序中 class 您应该为 WebApi 和 SignalR 注册 NinjectDependencyResolver,如下所示:
public void Configuration(IAppBuilder app)
{
var dependencyResolver = new NinjectDependencyResolver("*.dll");
var httpConfiguration = new HttpConfiguration();
httpConfiguration.DependencyResolver = dependencyResolver;
app.UseWebApi(httpConfiguration);
var hubConfig = new HubConfiguration { Resolver = dependencyResolver };
app.MapSignalR(hubConfig);
}
最后,我设法获得了支持 OWIN 管道、WebApi、MVC 和 SignalR 的工作 Ninject 配置。
当我发布问题时,我有一个解决方法(在 SignalR 集线器中禁用 DI)所以我决定不再浪费时间在这上面并继续前进。
但是当我尝试 运行 OWIN 内存中测试服务器与我的启动 class 时,发现 DI 不工作。 CreateKernel 方法调用得太晚,导致创建了一个在 sengleton 范围内使用的对象的多个实例。
在尝试了不同的初始化变体之后,我让 DI 可以用于 OWIN 测试服务器,它还修复了 SignalR DependencyResolver。
解决方法:
我停止使用包 Ninject.Web.Common.OwinHost 和 Ninject.Web.WebApi.OwinHost 因此这些调用已从我的配置方法中删除:
//app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
//app.UseNinjectWebApi(config);
我改为执行以下操作:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
NinjectWebCommon.Start();
config.DependencyResolver = new NinjectDependencyResolver(NinjectWebCommon.bootstrapper.Kernel);
app.UseWebApi(config);
app.MapSignalR();
}
public static class NinjectWebCommon
{
private static bool _isStarted;
internal static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
// When creating OWIN TestService instances during unit tests
// Start() method might be called several times
// This check ensures that Ninject kernel is initialized only once per process
if (_isStarted)
return;
_isStarted = true;
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
internal static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// DI for SignalR
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
// DI for MVC
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding code here
kernel.Bind<Something>().ToSelf().InSingletonScope();
}
}
必须在依赖注入配置之后配置 SignalR。因此,在您的 OWIN 启动 class 中,确保 app.MapSignalR()
在 之后被调用 设置 MVC 依赖解析器(System.Web.MVC.DependencyResolver
),WebApi 依赖解析器(System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver
) 和 SignalR 依赖解析器 (Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver
)。