OWIN + Ninject w/ UseNinjectMiddleware 不处理
OWIN + Ninject w/ UseNinjectMiddleware doesn't dispose
当使用 UseNinjectMiddleware
在 OWIN 中将 Ninject 内核注册为中间件组件时,任何实现 IDisposable 的注入对象都不会在请求结束时被释放。
我已经放入控制台打印以查看何时创建和处置实例。我注意到每个请求都会创建实例,但直到某个随机时间后才会被处理掉。
我创建了一个空项目来查找根本原因。
我使用了一个简单的模型来跟踪它的实例编号,这样我就可以知道正在创建和处理什么。
型号:
public class Demo : IDemo, IDisposable {
public static int InstanceCount = 1; //Tracks the current number of
//instances that have been created.
public Demo() {
Id = InstanceCount++;
Debug.WriteLine("Initialized Instance " + Id);
}
public int Id { get; set; }
public void Dispose() {
Debug.WriteLine("Disposed instance" + Id);
Id = -1;
}
}
public interface IDemo {
int Id { get; set; }
}
控制器
public class HomeController : Controller {
private readonly IDemo demo;
public HomeController(IDemo demo) { this.demo = demo; }
public ActionResult Index() {
ViewBag.Id = demo.Id;
return View();
}
}
启动文件
public class Startup {
public void Configuration(IAppBuilder app) {
var kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel);
}
public IKernel CreateKernel() {
var kernel = new StandardKernel();
kernel.Bind<IDemo>().To<Demo>().InRequestScope();
return kernel;
}
}
我还确保所有软件包都是最新的,因为这是 Ninject.
先前版本中的一个已知问题
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net462" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net462" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net462" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net462" />
<package id="Microsoft.Owin" version="4.0.1" targetFramework="net462" />
<package id="Microsoft.Owin.Host.SystemWeb" version="4.0.1" targetFramework="net462" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net462" />
<package id="Ninject" version="3.3.4" targetFramework="net462" />
<package id="Ninject.MVC5" version="3.3.0" targetFramework="net462" />
<package id="Ninject.Web.Common" version="3.3.1" targetFramework="net462" />
<package id="Ninject.Web.Common.OwinHost" version="3.3.1" targetFramework="net462" />
<package id="Ninject.Web.Common.WebHost" version="3.3.1" targetFramework="net462" />
<package id="Owin" version="1.0" targetFramework="net462" />
<package id="WebActivatorEx" version="2.2.0" targetFramework="net462" />
</packages>
预计
查看应用程序的主页时,每个请求都应打印出来:
Initialized Instance #
然后在请求结束时
Disposed instance #
其中#
是当前实例编号
实际
每次查看页面时只打印初始化。
Initialized Instance #
问题
我是不是做错了什么,或者这是 Ninject 和 Owin 的错误?有办法解决这个问题吗?
我在 GitHub 上提取了 Ninject.Web.Common 存储库的副本,并在 OwinHost 项目中对 OwinBootstrapper.cs 文件
进行了一些更改
我在 await next(context)
行
之后的 Execute 方法中添加了两行
var currentContext = HttpContext.Current;
this.bootstrapper.Kernel?.Components.Get<ICache>().Clear(currentContext);
public Func<IDictionary<string, object>, Task> Execute(Func<IDictionary<string, object>, Task> next)
{
this.bootstrapper.Initialize(() =>
{
var kernel = this.createKernelCallback();
lock (this.modules)
{
kernel.Load(this.modules);
}
return kernel;
});
return async context =>
{
using (var scope = new OwinRequestScope())
{
context[NinjectOwinRequestScope] = scope;
await next(context);
var currentContext = HttpContext.Current;
this.bootstrapper.Kernel?.Components.Get<ICache>().Clear(currentContext);
}
};
}
然后我将该项目构建为本地 nuget 包,并将 nuget 上引用的包替换为一个本地包。
当使用 UseNinjectMiddleware
在 OWIN 中将 Ninject 内核注册为中间件组件时,任何实现 IDisposable 的注入对象都不会在请求结束时被释放。
我已经放入控制台打印以查看何时创建和处置实例。我注意到每个请求都会创建实例,但直到某个随机时间后才会被处理掉。
我创建了一个空项目来查找根本原因。 我使用了一个简单的模型来跟踪它的实例编号,这样我就可以知道正在创建和处理什么。
型号:
public class Demo : IDemo, IDisposable {
public static int InstanceCount = 1; //Tracks the current number of
//instances that have been created.
public Demo() {
Id = InstanceCount++;
Debug.WriteLine("Initialized Instance " + Id);
}
public int Id { get; set; }
public void Dispose() {
Debug.WriteLine("Disposed instance" + Id);
Id = -1;
}
}
public interface IDemo {
int Id { get; set; }
}
控制器
public class HomeController : Controller {
private readonly IDemo demo;
public HomeController(IDemo demo) { this.demo = demo; }
public ActionResult Index() {
ViewBag.Id = demo.Id;
return View();
}
}
启动文件
public class Startup {
public void Configuration(IAppBuilder app) {
var kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel);
}
public IKernel CreateKernel() {
var kernel = new StandardKernel();
kernel.Bind<IDemo>().To<Demo>().InRequestScope();
return kernel;
}
}
我还确保所有软件包都是最新的,因为这是 Ninject.
先前版本中的一个已知问题<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net462" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net462" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net462" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net462" />
<package id="Microsoft.Owin" version="4.0.1" targetFramework="net462" />
<package id="Microsoft.Owin.Host.SystemWeb" version="4.0.1" targetFramework="net462" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net462" />
<package id="Ninject" version="3.3.4" targetFramework="net462" />
<package id="Ninject.MVC5" version="3.3.0" targetFramework="net462" />
<package id="Ninject.Web.Common" version="3.3.1" targetFramework="net462" />
<package id="Ninject.Web.Common.OwinHost" version="3.3.1" targetFramework="net462" />
<package id="Ninject.Web.Common.WebHost" version="3.3.1" targetFramework="net462" />
<package id="Owin" version="1.0" targetFramework="net462" />
<package id="WebActivatorEx" version="2.2.0" targetFramework="net462" />
</packages>
预计
查看应用程序的主页时,每个请求都应打印出来:
Initialized Instance #
然后在请求结束时
Disposed instance #
其中#
是当前实例编号
实际
每次查看页面时只打印初始化。
Initialized Instance #
问题
我是不是做错了什么,或者这是 Ninject 和 Owin 的错误?有办法解决这个问题吗?
我在 GitHub 上提取了 Ninject.Web.Common 存储库的副本,并在 OwinHost 项目中对 OwinBootstrapper.cs 文件
进行了一些更改我在 await next(context)
行
var currentContext = HttpContext.Current;
this.bootstrapper.Kernel?.Components.Get<ICache>().Clear(currentContext);
public Func<IDictionary<string, object>, Task> Execute(Func<IDictionary<string, object>, Task> next)
{
this.bootstrapper.Initialize(() =>
{
var kernel = this.createKernelCallback();
lock (this.modules)
{
kernel.Load(this.modules);
}
return kernel;
});
return async context =>
{
using (var scope = new OwinRequestScope())
{
context[NinjectOwinRequestScope] = scope;
await next(context);
var currentContext = HttpContext.Current;
this.bootstrapper.Kernel?.Components.Get<ICache>().Clear(currentContext);
}
};
}
然后我将该项目构建为本地 nuget 包,并将 nuget 上引用的包替换为一个本地包。