为啥 autofac 在 HttpRequest 结束之前处理一个对象?
Posted
技术标签:
【中文标题】为啥 autofac 在 HttpRequest 结束之前处理一个对象?【英文标题】:Why is autofac disposing an object before the HttpRequest ends?为什么 autofac 在 HttpRequest 结束之前处理一个对象? 【发布时间】:2011-05-09 19:09:49 【问题描述】:我正在编写一个 ASP.NET MVC 网站,使用 autofac 进行依赖注入,并使用 Mindscape 的 Lightspeed 作为 ORM。有一个 UserRepository 类,它依赖于光速 UnitOfWork,并为 Logon 控制器提供服务。
问题:UnitOfWork 在 UserRepository 完成使用之前被释放。
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 (
【问题讨论】:
【参考方案1】:我能够找到问题所在 - 这是一个愚蠢但微妙的问题...... 我有一个 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 超过它所依赖的实例。
【讨论】:
以上是关于为啥 autofac 在 HttpRequest 结束之前处理一个对象?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 charles 无法通过 c++ 捕获 http 请求?