4

我正在编写一个 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 (

4

1 回答 1

5

我能够找到问题所在 - 这是一个愚蠢但微妙的问题......我有一个 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 超越它所依赖的实例。

于 2010-11-15T07:53:14.590 回答