Search code examples
c#genericssimple-injector

TornLifestyle simple injector


I have defined a generic interface like this:

public interface IPlanManagmentRepository<TEntity> where TEntity:class

When I define a concrete implementation like this:

public class ProviderPlanManagementRepo : IPlanManagmentRepository<Provider>

everything works by registering the interface like this:

container.Register(typeof(IPlanManagmentRepository<>), 
    new [] { typeof(IPlanManagmentRepository<>).Assembly}, 
    Lifestyle.Scoped);

However, If this class also handles more stuff and I add an extra interface:

public interface IProviderPlanManagementRepo
{
    void doSomethingSpecificToProviderHere();
}
public class ProviderPlanManagementRepo : IProviderPlanManagementRepo,
    IPlanManagmentRepository<Provider>
{
}

Then I get this error:

-[Torn Lifestyle] The registration for IPlanManagmentRepository maps to the same implementation and lifestyle as the registration for IProviderPlanManagementRepo does. They both map to ProviderPlanManagementRepo

I also tried to inherit IPlanManagmentRepository in IProviderPlanManagementRepo but got the same error.

Should this class only handle the implementation from the generic interface? or is possible to accomplish this with simple injector?


Solution

  • UPDATE:

    With the introduction of Simple Injector 4, the container will prevent the creation of multiple Registration instances for the same concrete type in most cases. The Torn Lifestyles warning type should therefore be extremely rare. Torn lifestyles will only happen when a custom lifestyle circumvents the caching behavior of the Lifestyle.CreateRegistration overloads.


    Your question is related to this work item and this discussion. Typically, torn lifestyles can be fixed as follows, but Simple Injector 3.1 makes it extraordinary hard to fix violations when types with multiple unrelated interfaces are registered using batch-registration. This is something we will address in one of the coming minor releases.

    The easiest fix I can recommend for now is to make your IPlanManagmentRepository<T> registrations transient. You should be able to make them transient, because your components should be immutable any way. So typically only the DbContext should be Scoped, but you might even not want to inject the DbContext into your repositories, since the DbContext is runtime data, and runtime data should not be injected into the components of your object graph.