2010-11-14 52 views
3

我正在写一个ASP.NET MVC网站,使用autofac进行依赖注入,Mindscape的Lightspeed作为ORM。有一个UserRepository类,它依赖于一个灯光的UnitOfWork,并且它为Logon控制器提供服务。为什么autofac在HttpRequest结束之前处理对象?

问题:前UserRepository被使用完的的UnitOfWork得到处理。

public class UserRepository : IUserRepository 
    { 
    private readonly BluechipModelUnitOfWork _unitOfWork; 

    public UserRepository(BluechipModelUnitOfWork unitOfWork) 
    { 
     _unitOfWork = unitOfWork; 
    } 
    public Principal GetPrincipal(string name) 
    { 
     // This line throws an ObjectDisposedException - UnitOfWork is already disposed. 
     return _unitOfWork.Principals.FirstOrDefault(p => p.Name == name); 
    } 
    ... 

在Global.asax中,如下依赖布线完成:

public class MvcApplication : HttpApplication, IContainerProviderAccessor 
{ 
    private static void RegisterAutofac() 
    { 
     var builder = new ContainerBuilder(); 

     // Register the lightspeed context as a singleton 
     builder.RegisterInstance(new LightSpeedContext<BluechipModelUnitOfWork>("LightSpeedBluechip")) 
      .As<LightSpeedContext<BluechipModelUnitOfWork>>() 
      .SingleInstance(); 

     // Register the unit of work constructor so that a new instance is bound to each HttpRequest 
     builder.Register(c => c.Resolve<LightSpeedContext<BluechipModelUnitOfWork>>().CreateUnitOfWork()) 
      .As<BluechipModelUnitOfWork>() 
      .InstancePerLifetimeScope(); 

     // Register user repository to be one instance per HttpRequest lifetime 
     builder.Register(c => new UserRepository(c.Resolve<BluechipModelUnitOfWork>())) 
      .As<IUserRepository>() 
      .InstancePerLifetimeScope(); 

     builder.Register(c => new CurrentUserService(
            c.Resolve<HttpSessionState>(), 
            c.Resolve<IUserRepository>(), 
            c.Resolve<IMembershipService>()) 
      ).As<ICurrentUserService>() 
      .CacheInSession(); 

     builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>(); 
     builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired().InjectActionInvoker(); 
     builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); 

     // Set the container provider up with registrations.  
     _containerProvider = new ContainerProvider(builder.Build()); 

     // Set the controller factory using the container provider.  
     ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(_containerProvider)); 

鉴于上述注册,为什么会被autofac处置的的UnitOfWork(

回答

2

我能够追查问题 - 这是一个愚蠢但微妙的陷阱... 我有一个CurrentUserService类,我注册如下:

builder.Register(c => new CurrentUserService(
            c.Resolve<HttpSessionState>(), 
            c.Resolve<IUserRepository>(), 
            c.Resolve<IMembershipService>()) 
      ).As<ICurrentUserService>() 
      .CacheInSession(); 

问题是CacheInSession(),因为CurrentUserService取决于IUserRepository,哪个autofac被忠实地注入,但随后在第一个请求结束时丢弃。

这使成光的东西很明显,但细微处注意连接最多依赖注射时:

确保高阶家属始终具有相同或使用寿命更短他们所依赖的服务。在我的情况下,溶液是改变上面的代码:

 builder.Register(c => new CurrentUserService(
            c.Resolve<HttpSessionState>(), 
            c.Resolve<IUserRepository>(), 
            c.Resolve<IMembershipService>()) 
      ).As<ICurrentUserService>() 
      .InstancePerLifetimeScope(); 

....其防止CurrentUserService来自离活其所依赖的实例。

相关问题