代码之家  ›  专栏  ›  技术社区  ›  Mark

为什么autopac在httpRequest结束之前处理对象?

  •  3
  • Mark  · 技术社区  · 14 年前

    我正在编写一个ASP.NET MVC网站,使用autopac进行依赖项注入,Mindscape的Lightspeed作为ORM。有一个userrepository类,它依赖于Lightspeed UnitOfWork,以及哪个服务于登录控制器。

    问题 :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));
    

    鉴于上述登记,为什么Autopac会处理UnitofWork?(

    1 回复  |  直到 14 年前
        1
  •  4
  •   Mark    14 年前

    我能找到问题所在-这是一个愚蠢但微妙的问题… 我注册了一个currentUserService类,如下所示:

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

    问题是 缓存会话() ,因为currentUserService依赖于iuserrepository,autopac忠实地注入了该库,但在第一个请求结束时进行了处理。

    这就揭示了在连接依赖注入时需要注意的一些明显而微妙的事情:

    确保高阶受抚养人始终拥有与其所依赖的服务相同或更短的寿命。在我的例子中,解决方案是更改上述代码:

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

    …这会阻止当前用户服务脱离它所依赖的实例。