OWIN + Ninject w / UseNinjectMiddleware не располагает - PullRequest
1 голос
/ 07 мая 2019

При регистрации ядра Ninject в качестве компонента промежуточного программного обеспечения в OWIN с использованием UseNinjectMiddleware любой внедренный объект, реализующий 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();
    }
}

Запускfile

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?Есть ли способ исправить эту проблему?

1 Ответ

0 голосов
/ 10 июля 2019

Я вытащил копию репозитория Ninject.Web.Common на GitHub, и в рамках проекта 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 на один локальный.

...