2011-02-28 17 views
24

Me sorprendió encontrar que al menos uno de mis objetos creados por Ninject no se elimina al final de la solicitud, cuando se ha definido como InRequestScopeNinject no llama Eliminar objetos cuando está fuera del alcance

Aquí es el objeto que estoy tratando de desechar:

Interfaz:

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

MessengerEntities es la aplicación de Entity Framework de ObjectContext - mi objeto de contexto.

Entonces crear una clase concreta de este modo:

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 
} 

Y luego tengo una fábrica de controlador Ninject como tal (esto se inspira en el libro de Steve Sanderson 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(); 
     } 
    } 
} 

Ahora, cuando pongo un punto de interrupción en la llamada a context.Dispose() en el objeto DataContext y ejecuto el depurador, ese código nunca se ejecuta.

Por lo tanto, la evidencia sugiere que Ninject no se deshace de los objetos cuando salen del alcance, sino que simplemente crea objetos nuevos y confía en el recolector de basura para deshacerse de ellos en el momento que elija.

Mi pregunta es: ¿debería preocuparme por esto? Debido a que lo soy, creo que Ninject eliminaría cualquier objeto que implemente IDisposable.

ACTUALIZACIÓN: He descargado las extensiones Ninject MVC (para MVC 3) y esto es ahora la forma en que estoy haciendo la MvcApplication y la unión, y que parece ser la eliminación de mi contexto del objeto.

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

y

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

Todo lo demás se mantiene igual.

Respuesta

15

Ninject eliminará sus objetos tan pronto como el GC recoja el objeto de solicitud. Pero normalmente esto lleva algo de tiempo. Pero hay una manera de forzar la eliminación anticipada después de que finalizara la solicitud. La mejor manera es usar Ninject.Web.MVC http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ en lugar de implementar su propia ControllerFactory. La otra forma es configurar su aplicación para usar el OnePerRequestModule.

+4

¡Impresionante, creo que está funcionando! No estoy seguro de cómo, pero descargué las extensiones Ninject MVC3, extendí NinjectHttpApplication en Global.asax, y creé una clase derivada de NinjectModule para definir mis enlaces, y voila, ahora está llamando a Dispose en mi clase DataContext. (Agregaré el código que estoy usando a mi pregunta y puede decirme si aún no lo estoy haciendo bien). ¡Gracias! – Cynthia

+2

Estoy usando 'Ninject.Web.MVC4' y mi' IDataContext' que es 'InRequestScope()' no está siendo eliminado. Agregué manualmente '' a 'system.web/httpModules' y eso tampoco funciona. ¿Alguna sugerencia? – epalm

+3

Extraño. Deshacerse en GC parece una derrota de propósito para mí. ¿Por qué la documentación de Ninject (https://github.com/ninject/ninject/wiki/Object-Scopes) anuncia Dispose al final de la solicitud si no lo hace? – Stilgar

Cuestiones relacionadas