Search code examples
c#asp.net-mvcunity-interception

Unity IoC Invalid Operation when change then lifetime manager in RegisterType


I have this configuration for my IoC with Unity in my MVC 4 project.

container.RegisterType<IDbContext, ConstructionRepositoryContext>("ConstructionRepositoryContext", new TransientLifetimeManager());
container.RegisterType<IDbContext, GeneralRepositoryContext>("GeneralRepositoryContext", new TransientLifetimeManager());

container.RegisterType<IUnitOfWork, UnitOfWork>(
    "ConstructionUnitOfWork",
    new InjectionConstructor(container.Resolve<IDbContext>("ConstructionRepositoryContext")));

container.RegisterType<IUnitOfWork, UnitOfWork>(
    "GeneralUnitOfWork",
    new InjectionConstructor(container.Resolve<IDbContext>("GeneralRepositoryContext")));

When I change TransientLifetimeManager by PerRequestLifetimeManager or something else, the following exception happen:

(Error in line 101)

Operation is not valid due to the current state of the object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Line 99:  new InjectionConstructor(container.Resolve<IDbContext>("ConstructionRepositoryContext")));
Line 100:
Line 101: container.RegisterType<IUnitOfWork, UnitOfWork>(
Line 102:   "GeneralUnitOfWork",
Line 103:   new InjectionConstructor(container.Resolve<IDbContext>("GeneralRepositoryContext")));

Solution

  • The exception is probably thrown at this line:

    container.Resolve<IDbContext>("ConstructionRepositoryContext"))
    

    This line is problematic, at the time when unity really resolves an IUnitOfWork (which could be another request), the IDbContext object resolved here has been destroyed.

    Try:

    container.RegisterType<IUnitOfWork, UnitOfWork>(
        "ConstructionUnitOfWork",
        new InjectionConstructor(new ResolvedParameter<IDbContext>("ConstructionRepositoryContext")));
    

    This tells the container that:

    When resolving the UnitOfWork with named "ConstructionUnitOfWork", use the constructor that takes a single IDbContext parameter, and when resolving that parameter, resolve using the name "ConstructionRepositoryContext"