Почему autofac удаляет объект до завершения HttpRequest? - PullRequest
3 голосов
/ 14 ноября 2010

Я пишу веб-сайт ASP.NET MVC, используя автофак для внедрения зависимостей, и Lightspeed Mindscape в качестве ORM.Есть класс UserRepository, который зависит от скорости света UnitOfWork и который обслуживает контроллер входа в систему.

Проблема : 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 Ответ

4 голосов
/ 15 ноября 2010

Мне удалось отследить проблему - это глупая, но тонкая ошибка ... У меня был класс 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 переиграть экземпляр, от которого он зависит.

...