超出范围时,Ninject不会调用对象上的Dispose

时间:2011-02-28 18:07:33

标签: entity-framework-4 asp.net-mvc-3 ninject idisposable

我很惊讶地发现Ninject创建的至少一个对象在请求结束时没有被处理掉,当它被定义为InRequestScope时

这是我试图处理的对象:

接口:

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

MessengerEntities是Entity Framework的ObjectContext实现 - 我的上下文对象。

然后我创建一个具体的类:

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();
        }
    }
}

现在,当我在DataContext对象中调用context.Dispose()并运行调试器时放置一个断点,该代码永远不会被执行。

因此,证据表明Ninject在超出范围时不会处置对象,而只是创建新对象并依赖垃圾收集器在其选择时将其删除。

我的问题是:我应该关注这件事吗?因为我 - 我认为Ninject会处理任何实现IDisposable的对象。

UPDATE:我下载了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 个答案:

答案 0 :(得分:15)

一旦GC收集了请求对象,Ninject就会处理您的对象。但通常需要一些时间。但是有一种方法可以在请求结束后强行提前处理。最好的方法是使用Ninject.Web.MVC http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/而不是实现自己的ControllerFactory。另一种方法是将您的应用程序配置为使用OnePerRequestModule。