我已设法通过以下方法使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 } }
到现在为止还挺好.
所有这一切都在使用Global.asax初始化的Web Api.
现在我正在切换到OWIN管道.所以我删除了GlobalConfiguration.Configure(WebApiConfig.Register);来自Global.asax并补充说
HttpConfiguration config = new HttpConfiguration(); WebApiConfig.Register(config); app.UseWebApi(config);
到我的OwinStartup课程. DI用于Web 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")]
这些行被禁用以避免两次初始化内核.
这个固定DI用于Web 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
我有点迷茫.我读过两篇文章,但没有一篇给我解决方案.非常感谢任何帮助.
我的最终目标是拥有一个服务于Web Api,MVC和SignalR的内核,并支持OWIN管道.
编辑:由于我得到一个评论,我的案件可能与另一个问题重复,我相信我需要给出一些解释.
我有三个场景.
>使用GlobalConfiguration.Configure(WebApiConfig.Register)在Global.asax中进行WebApi初始化,使用NinjectWebCommon和Bootstrapper进行Ninject初始化.
这给了我注入WebApi和SignalR.但由于我想将WebApi初始化移动到OWIN启动,这种方法已经过时了.
>使用OWIN启动进行WebApi初始化,使用NinjectWebCommon和Bootstrapper进行Ninject初始化.
SignalR注入工作,WebApi注入不起作用.
>使用OWIN启动进行WebApi初始化,使用UseNinjectMiddleware进行Ninject初始化,使用UseNinjectWebApi.
WebApi注入工作,SignalR注入不起作用.
所以基本上我需要弄清楚如何把它放在一起,这样当我在OWIN管道上初始化WebApi时,WebApi和SignalR注入都能正常工作.
NinjectWebCommon的代码在下面是原始问题.它包含用于创建SignalR解析器的代码,但在方案3中没有帮助.
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再次开始工作.但当然没有在集线器内注入.
解决方法
当我发布问题时,我有一个解决方法(在SignalR集线器中禁用了DI),所以我决定不再浪费时间在这上面并继续前进.
但是,当我尝试使用我的启动类运行OWIN内存测试服务器时,发生DI无法正常工作.调用CreateKernel方法太晚,导致创建了在sengleton范围内使用的对象的多个实例.
在使用不同的初始化变体后,我已经使DI工作为OWIN测试服务器,它还修复了SignalR DependencyResolver.
解决方案:
我停止使用Ninject.Web.Common.OwinHost和Ninject.Web.WebApi.OwinHost包这些调用从我的Configuration方法中删除了:
//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(); } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。