I am using Simple Injector as my IoC container and employ the following technique to enable registering a "mixed" lifestyle for some objects as both per web request or per thread.
interface IUnitOfWork { }
interface IWebUnitOfWork : IUnitOfWork { }
interface IThreadUnitOfWork : IUnitOfWork { }
class UnitOfWork : IWebUnitOfWork, IThreadUnitOfWork { }
container.RegisterPerWebRequest<IWebUnitOfWork, UnitOfWork>();
container.RegisterLifetimeScope<IThreadUnitOfWork, UnitOfWork>();
container.Register<IUnitOfWork>(() => container.GetInstance<UnitOfWork>());
// Register as hybrid PerWebRequest / PerLifetimeScope.
container.Register<UnitOfWork>(() =>
{
if (HttpContext.Current != null)
return container.GetInstance<IWebUnitOfWork>() as UnitOfWork;
else
return container.GetInstance<IThreadUnitOfWork>() as UnitOfWork;
});
I am not entirely satisfied with this solution as for each requirement I must define extra empty interfaces to make it work and ensure they are referenced by my concrete class.
Is there any reason I should not use the following extension methods instead of defining the extra interfaces? If there is some issue with these methods is there some other way to establish, with complete confidence, that my current instance of the container is running within IIS?
public static void RegisterHybridLifestyle<TService, TImplementation>(
this Container container)
where TService : class
where TImplementation : class, TService
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TService, TImplementation>();
else
container.RegisterLifetimeScope<TService, TImplementation>();
}
public static void RegisterForLifestyle<TConcrete>(
this Container container)
where TConcrete : class
{
if (HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TConcrete>();
else
container.RegisterLifetimeScope<TConcrete>();
}
UPDATE
The above question and this follow on question were based on a misunderstanding of SimpleInjector and hybrid registration. The techniques described above and elsewhere on SO are for when the container can be servicing request for both Web Requests and for background processes that are not running within the context of a web request. What I have been trying to achieve is variable registration to cater for a configuration of the container that is suitable for both Web Request OR Thread Request. i.e. I need to configure my container to work within IIS and to work within a windows service. I don't need the dynamic registration that can cater for both a the same time.
The outcome of this is the following extension methods and I have removed the "extra" interfaces from my solution :-)
public static void RegisterForScope<TService, TImplementation>(this Container container)
where TService : class
where TImplementation : class, TService
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TService, TImplementation>();
else
container.RegisterLifetimeScope<TService, TImplementation>();
}
public static void RegisterForScope<TConcrete>(this Container container)
where TConcrete : class
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TConcrete>();
else
container.RegisterLifetimeScope<TConcrete>();
}