Ninject не вызывает Dispose для объектов, когда они находятся вне области видимости - PullRequest
25 голосов
/ 28 февраля 2011

Я был удивлен, обнаружив, что хотя бы один из моих объектов, созданных Ninject, не удаляется в конце запроса, когда он определен как InRequestScope

Вот объект, который я пытаюсьраспоряжаться:

Интерфейс:

public interface IDataContext : IDisposable
{
    MessengerEntities context { get; set; }
}

MessengerEntities - реализация ObjectContext Entity Framework - моего объекта контекста.

Затем я создаю конкретный класс, например:

public class DataContext : IDataContext
{
    private MessengerEntities _context = new MessengerEntities();
    public MessengerEntities context
    {
        get
        {
            return _context;
        }
        set
        {
            _context = value;
        }
    }
    #region IDisposable Members

    public void Dispose()
    {
        context.Dispose();
    }

    #endregion
}

А потом у меня есть фабрика контроллеров Ninject, подобная этой (это смоделировано в книге Стива Сандерсона MVC 2):

public class NinjectControllerFactory : DefaultControllerFactory
{
    // a Ninject "kernel" is the thing that can supply object instances
    private IKernel kernel = new StandardKernel(new MessengerServices());

    // ASP.NET MVC calls this to get the controller for each request
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
            return null;
        return (IController)kernel.Get(controllerType);
    }

    private class MessengerServices : NinjectModule
    {
        public override void Load()
        {
            Bind<IDataContext>().To<DataContext>().InRequestScope();
            Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
            Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
        }
    }
}

Теперь, когда я ставлю точку останова при вызовеcontext.Dispose () в объекте DataContext и запускает отладчик, этот код никогда не выполняется.

Итак, данные свидетельствуют о том, что Ninject не избавляется от объектов, когда они выходят из области видимости, а просто создает новые объектыи полагается на сборщик мусора, чтобы избавиться от них во время своего выбора.

Мой вопрос: должен ли я беспокоиться об этом?Потому что я - я думаю, Ninject избавится от любого объекта, который реализует IDisposable.

ОБНОВЛЕНИЕ: Я скачал расширения Ninject Mvc (для MVC 3), и теперь я такя делаю MvcApplication и привязку, и он, похоже, избавляется от моего объекта контекста.

В global.asax:

public class MvcApplication : NinjectHttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

    }

    protected override Ninject.IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
        return kernel;
    }

    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }
}

и

public class EFBindingModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDataContext>().To<DataContext>().InRequestScope();
        Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
        Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
    }
}

Все остальное остается прежним.

1 Ответ

15 голосов
/ 28 февраля 2011

Ninject утилизирует ваши объекты, как только объект запроса будет собран GC. Но обычно это занимает некоторое время. Но есть способ заставить досрочное удаление после того, как запрос закончился. Лучше всего использовать Ninject.Web.MVC http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ вместо реализации собственной ControllerFactory. Другой способ - настроить приложение на использование модуля OnePerRequestModule.

...