SimpleInjector mixed lifestyle for per web request and lifetime scope - c#

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>();
}

I am not entirely satisfied with this solution
Yes, I agree with this. To be honest, having to do things like this actually sucks IMO. That's why this is fixed in Simple Injector 2.0. It contains the explicit notion of lifestyle and it will contain a Lifestyle.CreateHybrid method, that makes it much easier to register hybrid lifestyles.
You however, don't seem to need a hybrid lifestyle add all. A hybrid lifestyle is a lifestyle that can switch dynamically (on each call to GetInstance<T> and per each injection), while you only seem to need to switch during start-up. I see no harm in using the RegisterHybridLifestyle extension method as you defined it, but keep in mind that this is not really an hybrid lifestyle (so the name is a bit misleading), but simply a configuration/deployment-switch.
Simple Injector 2 and up make this much easier, and it will allow you to do something like this:
// Define a lifestyle once based on the deployment.
Container.Options.DefaultScopedLifestyle =
Lifestyle.CreateHybrid(
lifestyleSelector: HostingEnvironment.ApplicationHost != null,
trueLifestyle: new WebRequestLifestyle(),
falseLifestyle: new LifetimeScopeLifestyle());
// And use it for registering the unit of work
// (no extra interfaces needed anymore).
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
// After setting DefaultScopedLifestyle, you can usr Lifestyle.Scoped
container.RegisterCollection(
typeof(ISubscriber<>),
new [] { typeof(ISubscriber<>).Assembly },
Lifestyle.Scoped);

Related

ASP.NET Core 2.1 Service Locator with Simple Injector returning null

I have an .NET MVC 5 .NET Framework Application which I am converting to .NET Core 2.1
I have a custom action filter which in .NET Framework version was registered as a Global Filter in a Filterconfig class like below:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyCustomActionFilter());
}
}
Within the custom action filter in the .NET version I was using Service Locator pattern (I know it can be considered an anti pattern) as below:
var myService = DependencyResolver.Current.GetService<IMyService>();
I am using Simple Injector for DI and everything works fine in the .NET Version. With the .NET Core version I am trying to get the same functionality working but myService is always null
I am still using Simple Injector (as all the other projects in the solution use it and they are not getting move to .NET Core projects (only the web one is).
My Startup.cs class has this code:
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter());
});
SimpleInjectorConfig.IntegrateSimpleInjector(services, container);
At my service layer I have a SimpleInjector Registartion class that gets called from Web Layer - it then calls down to DAL Layer to do Registration
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container)
{
container.Register<IMyService, MyService>();
//further code removed for brevity
When I run the application with a breakpoint in the Custom Filter and a breakpoint in this RegisterServices method I can see the breakpoint in the RegisterServices method gets hit first and then the breakpoint in the Custom Filter - this made me think everything was wired up in the container correctly.
However I am trying to do the below again in the custom filter with .NET Core Service Locator pattern
var myService = filterContext.HttpContext.RequestServices.GetService<IMyService>();
but the result is always null?
Is there something I have missed in this setup?
------------ UPDATE -------------------
Based on Stevens comment I added a constructor to my action filter and passed in the Simple Injector container.
So My Startup class now is:
public class Startup
{
//Simple Injector container
private Container container = new Container();
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter(container));
My Custom filter now is like below with constructor added:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//actual code of custom filter removed - use of MyService
I set a breakpoint on the Constructor of MyCustomActionFilter and I can see it getting hit but I get an Error thrown:
SimpleInjector.ActivationException: 'The IDbContext is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.'
MyService has a Dependency on the DbContext which is injected into it (it is doing work saving and retrieving data from DB.
For the DB Context I registered it as below:
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container, string connectionString)
{
container.Register<IDbContext>(() => new MyDbContext(connectionString),
Lifestyle.Scoped);
}
}
There are some significant changes between how to integrate Simple Injector in the old ASP.NET MVC and the new ASP.NET Core. In the old system, you would be able to replace the IDependencyResolver. ASP.NET Core, however, contains a completely different model, with its own internal DI Container. As it is impossible to replace that built-in container with Simple Injector, you will have the two containers run side-by-side. In that case the built-in container will resolve framework and third-party components, where Simple Injector will compose application components for you.
When you call HttpContext.RequestServices.GetService, you will be requesting the built-in container for a service, not Simple Injector. Adding the IMyService registration to the built-in container, as TanvirArjel's answer suggests, might seem to work at first, but that completely skips Simple Injector from the equation, which is obviously not an option, as you wish to use Simple Injector as your application container.
To mimic the Service Locator-like behavior you had before, you will have to inject the SimpleInjector.Container into your filter, as follows:
options.Filters.Add(new MyCustomActionFilter(container));
It would be an error, however, to call the container from within the constructor, as you are showing in your question:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>(); // NEVER DO THIS!!!
}
...
}
WARNING: You should never resolve from the container from the constructor. Or in more general: you should never use any injected dependency from inside the constructor. The constructor should only store the dependency.
As Mark Seemann explained, injection constructors should be simple. In this case, it even gets worse because:
During the time that the constructor of MyCustomActionFilter is invoked, there is no active scope, and IMyService can't be resolved
Even if IMyService could be resolved, MyCustomActionFilter is a Singleton and storing IMyService in a private field will cause a hidden Captive Dependency. This could lead to all sorts of trouble.
Instead of storing the resolved, IMyService dependency, you should store the Container dependency:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly Container _container;
public MyCustomActionFilter(Container container)
{
_container = container;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
myService = container.GetService<IMyService>();
//actual code of custom filter removed - use of MyService
}
}
During the time that OnActionExecuting is called, there will be an active Simple Injector Scope, which will allows IMyService to be resolved. On top of that, as IMyService is not stored in a private field, it will not be cached and will not cause a Captive Dependency.
In your question you referred to the Service Locator anti-pattern. Whether or not the injection of the Container into your filter is in fact an implementation of the Service Locator anti-pattern depends on where the filter is located. As Mark Seemann puts it:
A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.
In other words, as long as the filter class is located inside your Composition Root, you are not applying the Service Locator anti-pattern. This does mean, however, that you must make sure that the filter itself contains as little interesting behavior as possible. That behavior should all be moved to the service that the filter resolves.
As #Steven points out, the built-in container will resolve framework and third-party components, where Simple Injector will compose application components for you. For built-in container, it could not resolve the service from simple injector. For simple injector, you could try EnableSimpleInjectorCrossWiring to resolve services from built-in container.
For options.Filters.Add, it also accepts MyCustomActionFilter instance, without resigering Container as depedence into MyCustomActionFilter, you could try register MyCustomActionFilter in sample injector, and then pass this instance to options.Filters.Add.
Register Services
private void InitializeContainer(IApplicationBuilder app)
{
// Add application presentation components:
container.RegisterMvcControllers(app);
container.RegisterMvcViewComponents(app);
// Add application services. For instance:
container.Register<IMyService, MyService>(Lifestyle.Scoped);
container.Register<MyCustomActionFilter>(Lifestyle.Scoped);
// Allow Simple Injector to resolve services from ASP.NET Core.
container.AutoCrossWireAspNetComponents(app);
}
add MyCustomActionFilter
services.Configure<MvcOptions>(options =>
{
using (AsyncScopedLifestyle.BeginScope(container))
{
options.Filters.Add(container.GetRequiredService<MyCustomActionFilter>());
}
});
#region SampleInjector
IntegrateSimpleInjector(services);
#endregion
Note If you specify container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();, you will need using (AsyncScopedLifestyle.BeginScope(container)) when you call container.GetRequiredService<MyCustomActionFilter>().

Windsor container. Lifetime of objects in ASP.NET MVC application

I have a new project where Windsor container is used for IoC.
Here is simplified code executed in Install
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(),
Component.For<ISecurityManager>().ImplementedBy<SecurityManager>(),
Component.For<IAccountManager>().ImplementedBy<AccountManager>()
........)
}
Information that I found in official documenation is not enough for understand in detail these lines.
Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(),
This line in Register method enables dependency injection to all classes in my application that are inherited from BaseController.
BaseController is included.
Injection will not be made to other classes than described above.
We show to container that lifetime of all controllers classes will be an instance.
Component.For<ISecurityManager>().ImplementedBy<SecurityManager>()
To all controllers registered above, if they have in constructor interface ISecurityManager will be injected instance of class SecurityManager.
Lifetime of this SecurityManager is singleton as default value. So after application start we will have only one instance of SecurityManager for all controllers till the end of application execution.
Are my ideas correct? It seems that not, at least because LifestyleTransient() for controllers seems to me strange and that injected objects will be singletons too.
From bottom to the top :
Lifetime of this SecurityManager is singleton as default value. So after application start we will have only one instance of SecurityManager for all controllers till the end of application execution.
Exactly this is going to happen.
It seems that not, at least because LifestyleTransient() for controllers seems to me strange and that injected objects will be singletons too.
Controllers are transient because they hold the HttpContext - they have the information about the current user request and the following response. This is why they are transients and not singletons - the HttpContext is per request and it is created every time a browser/client requests something.
So it is understandable why controllers have shorter lifespan than your other services. It greatly depends on the inner architecture of the application. If someone else has a better idea why - I am more than willing to learn.
The Register/Resolve/Release cycle of your controllers can be done by creating a custom controller factory and substituting the default :
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
if (_kernel.GetHandler(controllerType) != null)
{
return (IController)_kernel.Resolve(controllerType);
}
return base.GetControllerInstance(requestContext, controllerType);
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
}
and somewhere put :
container.Register(Component.For<IControllerFactory>().ImplementedBy<WindsorControllerFactory>());
My controllers too have singleton dependenices. In this way you can achieve a pipeline programming model - you funnel the request from the controller through a series of objects and than return the results.
If SecurityManager has something to do with Authentication or Authorization it maybe better to use the MVC default Filtering mechanisms like IAuthorizationFilter or AuthorizeAttribute. Of course this maybe data access filter and it may be reasonable to put it in a different object.
Did I answer your questions?

How do I control the lifetime of a custom IResourceProvider?

I've taken this approach to injecting a custom resource provider in my ASP.NET MVC application, but I'm having some problems with object lifetime management.
I'm using Castle Windsor, so I have the following implementation of the factory:
public class DefaultResourceProviderFactory : ResourceProviderFactory
{
public override IResourceProvider CreateGlobalResourceProvider(string classKey)
{
// IoC is a static helper class that gives me static access to the
// container. IoC.Resolve<T>(args...) simply calls container.Resolve<T>(args...).
return IoC.Resolve<IResourceProvider>(new { resourceType = "Global" });
}
public override IResourceProvider CreateLocalResourceProvider(string virtualPath)
{
// resourceType
return IoC.Resolve<IResourceProvider>(new { ResourceType = virtualPath });
}
}
However, the IResourceProvider I have registered in the container doesn't seem to have its lifetime managed correctly. It has some other dependencies of its own, some of which have somewhat complicated lifestyles (per web request or per transaction), so I've registered the IResourceProvider as transient to ensure that its dependencies are always valid. But the MVC framework is stepping on my toes, keeping a reference to the IResourceProvider across web requests, which causes ObjectDisposedExceptions when its dependencies have been invalidated on the next request.
What I'd like to do, is to make the MVC framework use the factory every time it needs an instance of my IResourceProvider, and - if possible - also to invoke IoC.Release(provider) or something similar when it's done with it.
How do I micro-manage the lifestyle of the custom IResourceProvider in a way that the MVC framework will respect?
After searching around for various ways to control the lifetime of the IResourceProvider itself, I decided that it was better to refactor my implementation to utilize the Typed Factory Facility.
My IResourceProvider implementation formerly looked something like this:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepository repo) { /* ... */ }
// other members...
}
Now, I changed it to this instead:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepositoryFactory repo) { /* ... */ }
// other members...
}
The factory interface is a new one, defined as
public interface IResourceRecordRepositoryFactory {
IResourceRecord NewInstance();
void Release(IResourceRecord instance);
}
and every usage of the private _repo instance in the CachedResourceProvider was refactored to three statements: get a repo instance from the factory, use the repo instance to fetch/save something, release the instance through the factory.
I registered them like this:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IResourceRecordRepositoryFactory>().AsFactory());
Now, even though MVC is keeping a reference to my resource provider across web requests, the services it uses are re-fetched from the Windsor container each time they're used, so the container is in full control of their lifetime.

Simple Injector: Inject same UnitOfWork instance across services of the same graph

I have multiple services, each of which have a UnitOfWork injected into the constructor using the Simple Injector IoC container.
Currently I can see each UnitOfWork instance is a separate object, this is bad as i am using Entity Framework and require the same context reference across all units of work.
How can I ensure the same UnitOfWork instance is injected into all services per each resolve request? My UnitOfWor will be saved by an external command handler decorator after the command completes.
Please note, this is a common library and will be used for both MVC and Windows Forms, it would be nice to have a generic solution for both platforms if possible.
Code is below:
// snippet of code that registers types
void RegisterTypes()
{
// register general unit of work class for use by majority of service layers
container.Register<IUnitOfWork, UnitOfWork>();
// provide a factory for singleton classes to create their own units of work
// at will
container.RegisterSingle<IUnitOfWorkFactory, UnitOfWorkFactory>();
// register logger
container.RegisterSingle<ILogger, NLogForUnitOfWork>();
// register all generic command handlers
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// register services that will be used by command handlers
container.Register<ISynchronisationService, SynchronisationService>();
container.Register<IPluginManagerService, PluginManagerService>();
}
The desired outcome of the below line is to create a object which has a shared UnitOfWork instance throughout the constructed object graph:
var handler = Resolve<ICommandHandler<SyncExternalDataCommand>>();
Here are my services:
public class PluginManagerService : IPluginSettingsService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void IPluginSettingsService.RegisterPlugins()
{
// manipulate the unit of work
}
}
public class SynchronisationService : ISynchronisationService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void ISynchronisationService.SyncData()
{
// manipulate the unit of work
}
}
public class SyncExternalDataCommandHandler
: ICommandHandler<SyncExternalDataCommand>
{
ILogger logger;
ISynchronisationService synchronisationService;
IPluginManagerService pluginManagerService;
public SyncExternalDataCommandHandler(
ISynchronisationService synchronisationService,
IPluginManagerService pluginManagerService,
ILogger logger)
{
this.synchronisationService = synchronisationService;
this.pluginManagerService = pluginManagerService;
this.logger = logger;
}
public void Handle(SyncExternalDataCommand command)
{
// here i will call both services functions, however as of now each
// has a different UnitOfWork reference internally, we need them to
// be common.
this.synchronisationService.SyncData();
this.pluginManagerService.RegisterPlugins();
}
}
Which registration you need depends on the type of application. Since you are talking about two different frameworks (MVC and WinForms), both will have a different registration.
For an MVC application (or web applications in general), the most common thing to do is to register the unit of work on a per web request basis. For instance, the following registration will cache the unit of work during a single web request:
container.Register<IUnitOfWork>(() =>
{
var items = HttpContext.Current.Items;
var uow = (IUnitOfWork)items["UnitOfWork"];
if (uow == null)
{
items["UnitOfWork"] = uow = container.GetInstance<UnitOfWork>();
}
return uow;
});
The downside of this registration is that the unit of work is not disposed (if needed). There is an extension package for the Simple Injector that adds RegisterPerWebRequest extension methods to the container, which will automatically ensure that the instance is disposed at the end of the web request. Using this package, you will be able to do the following registration:
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new WebRequestLifestyle());
A Windows Forms application on the other hand, is typically single threaded (a single user will be using that application). I believe it is not unusual to have a single unit of work per form, which is disposed the form closes, but with the use of the command/handler pattern, I think it is better to take a more service oriented approach. What I mean by this is that it would be good to design it in such way that you can move the business layer to a WCF service, without the need to make changes to the presentation layer. You can achieve this by letting your commands only contain primitives and (other) DTOs. So don't store Entity Framework entities into your commands, because this will make serializing the command much harder, and it will lead to surprises later on.
When you do this, it would be convenient to create a new unit of work before the command handler starts executing, reuse that same unit of work during the execution of that handler, and commit it when the handler completed successfully (and always dispose it). This is a typical scenario for the Per Lifetime Scope lifestyle. There is an extension package that adds RegisterLifetimeScope extension methods to the container. Using this package, you will be able to do the following registration:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new LifetimeScopeLifestyle());
The registration however, is just half of the story. The second part is to decide when to save the changes of the unit of work, and in the case of the use of the Lifetime Scope lifestyle, where to start and end such a scope. Since you should explicitly start a lifetime scope before the command executes, and end it when the command finished executing, the best way to do this, is by using a command handler decorator, that can wrap your command handlers. Therefore, for the Forms Application, you would typically register an extra command handler decorator that manages the lifetime scope. This approach does not work in this case. Take a look at the following decorator, but please note that it is incorrect:
private class LifetimeScopeCommandHandlerDecorator<T>
: ICommandHandler<T>
{
private readonly Container container;
private readonly ICommandHandler<T> decoratedHandler;
public LifetimeScopeCommandHandlerDecorator(...) { ... }
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
// WRONG!!!
this.decoratedHandler.Handle(command);
}
}
}
This approach does not work, because the decorated command handler is created before the lifetime scope is started.
We might be tempted into trying to solve this problem as follows, but that isn't correct either:
using (this.container.BeginLifetimeScope())
{
// EVEN MORE WRONG!!!
var handler = this.container.GetInstance<ICommandHandler<T>>();
handler.Handle(command);
}
Although requesting an ICommandHandler<T> inside the context of a lifetime scope, does indeed inject an IUnitOfWork for that scope, the container will return a handler that is (again) decorated with a LifetimeScopeCommandHandlerDecorator<T>. Calling handler.Handle(command) will therefore result in a recursive call and we'll end up with a stack overflow exception.
The problem is that the dependency graph is already built before we can start the lifetime scope. We therefore have to break the dependency graph by deferring building the rest of the graph. The best way to do this that allows you to keep your application design clean] is by changing the decorator into a proxy and injecting a factory into it that will create the type that it was supposed to wrap. Such LifetimeScopeCommandHandlerProxy<T> will look like this:
// This class will be part of the Composition Root of
// the Windows Forms application
private class LifetimeScopeCommandHandlerProxy<T> : ICommandHandler<T>
{
// Since this type is part of the composition root,
// we are allowed to inject the container into it.
private Container container;
private Func<ICommandHandler<T>> factory;
public LifetimeScopeCommandHandlerProxy(Container container,
Func<ICommandHandler<T>> factory)
{
this.factory = factory;
this.container = container;
}
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
var handler = this.factory();
handler.Handle(command);
}
}
}
By injecting a delegate, we can delay the time the instance is created and by doing this we delay the construction of (the rest of) the dependency graph. The trick now is to register this proxy class in such way that it will inject the wrapped instances, instead of (of course) injecting itself again. Simple Injector supports injecting Func<T> factories into decorators, so you can simply use the RegisterDecorator and in this case even the RegisterSingleDecorator extension method.
Note that the order in which decorators (and this proxy) are registered (obviously) matters. Since this proxy starts a new lifetime scope, it should wrap the decorator that commits the unit of work. In other words, a more complete registration would look like this:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Register a decorator that handles saving the unit of
// work after a handler has executed successfully.
// This decorator will wrap all command handlers.
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Register the proxy that starts a lifetime scope.
// This proxy will wrap the transaction decorators.
container.RegisterSingleDecorator(
typeof(ICommandHandler<>),
typeof(LifetimeScopeCommandHandlerProxy<>));
Registering the proxy and decorator the other way around would mean that the TransactionCommandHandlerDecorator<T> would depend on a different IUnitOfWork than the rest of the dependency graph does, which would mean that all changes made to the unit of work in that graph will not get committed. In other words, your application will stop working. So always review this registration carefully.
Good luck.

how to implement IOC without a global static service (non-service locator solution)?

we want to use Unity for IOC.
All i've seen is the implementation that there is one global static service (let's call it the the IOCService) which holds a reference to the Unity container, which registers all interface/class combinations and every class asks that object: give me an implementation for Ithis or IThat.
Frequently i see a response that this pattern is not good because it leads to a dependency from ALL classes to the IOCService (not to the Unity container because it is only known inside the IOCService).
But what i don't see often, is: what is the alternative way?
Michel
EDIT: found out that the global static service is called the service locator, added that to the title.
The alternative is to have a single instance of your container at the highest application level only, then use that container to resolve every object instance you need to create in that layer.
For example, the main method of most executables just looks like this (minus exception handling):
private static void main(string[] args) {
Container container = new Container();
// Configure the container - by hand or via file
IProgramLogic logic = container.Resolve<IProgramLogic>();
logic.Run();
}
Your program (represented here by the IProgramLogic instance) doesn't have to know anything about your container, because container.Resolve will create all its dependencies - and its dependencies' dependencies, on down to leaf classes with no dependencies of their own.
ASP.NET is a harder case, because web forms doesn't support constructor injection. I typically use Model-View-Presenter in my web forms applications, so my Page classes really only have one dependency each - on their presenter. I don't unit test them (everything interesting and testable is in my presenters, which I do test), and I don't ever substitute presenters. So I don't fight the framework - I just expose a container property on my HttpApplication class (in global.asax.cs) and use it directly from my Page files:
protected void Page_Load(object sender, EventArgs args) {
ICustomerPresenter presenter = Global.Container.Resolve<ICustomerPresenter>();
presenter.Load();
}
That's service locator of course - though the Page classes are the only thing coupled to the locator: your presenter and all of its dependencies are still fully decoupled from your IoC container implementation.
If you have a lot of dependencies in your Page files (that is, if you do not use Model-View-Presenter), or if it's important to you to decouple your Page classes from your Global application class, you should try to find a framework that integrates into the web forms request pipeline and use property injection (as suggested by Nicholas in the comments below) - or write your own IHttpModule and perform the property injection yourself.
+1 for knowing that Service Locator is a Bad Thing.
Problem is - Unity is not very sophisticated so I don't know how easy/hard is it to do IoC the right way with it.
I wrote few blogposts recently that you might find useful.
How I use IoC Containers
Pulling from the container
Instead of using the container explicitly, use it implicitly by leveraging constructor / property injection instead. Create a core class (or set of core classes) that depend on all the major pieces of your application.
Most containers will let you put ISomething[] in your constructor and it will inject all instances of ISomething into your class.
This way, when you bootstrap your application:
Instantiate your container
Register all your goodies
Resolve the core classes (this will pull in all the other dependencies you need)
Run the "main" part of the application
Now, depending on the type of application you are writing, there are different strategies for avoiding marking the IoC container as "static".
For ASP.NET web applications, you'll probably end up storing the container in the Application State. For ASP.NET MVC applications, you need to change out the Controller Factory.
For desktop applications, things get more complicated. Caliburn uses an interesting solution to this problem using the IResult construct (this is for WPF applications but could be adapted for Windows Forms as well.
In theory, to not have to worry about having a static IoC instance, you need to follow the Fight Club Rule - i.e. not to talk about the fight club - i.e. not to mention the IoC container.
This means that your components should largely be unaware about the IoC container. It should only be used at the topmost level when registering components. If a class needs to resolve something, it should really be injected as a dependency.
The trivial case is easy enough. If PaymentService depends on IAccount, the latter should be injected by IoC:
interface IAccount {
Deposit(int amount);
}
interface CreditCardAccount : IAccount {
void Deposit(int amount) {/*implementation*/}
int CheckBalance() {/*implementation*/}
}
class PaymentService {
IAccount account;
public PaymentService (IAccount account) {
this.account = account;
}
public void ProcessPayment() {
account.Deposit(5);
}
}
//Registration looks something like this
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
The not so trivial case is where you want to inject multiple registrations. This especialy applies when you are doing any sort of Converntion Over Configuration and creating an object from a name.
For our payment example, say you want to enumerate through all accounts and check their balances:
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IEnumerable<IAccount> accounts) {
this.accounts = accounts;
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
Unity has the ability to register multiple interface to class mappings (they have to have different names thought). It does not, however, automatically inject those into classes that take collections of those registered interfaces. So, the above example will throw a resolution failed exception at runtime.
If you don't care that those objects live forever, you can register PaymentService in a more static fashion:
container.RegisterType<PaymentService>(new InjectionConstructor(container.ResolveAll<IAccount>()));
The above code will register PaymentService and will use a collection of IAccount instances that is resolved at registration time.
Alternatively, you can pass an instance of the container itself as a dependency and let PaymentService perform resolution of accounts. This is not quite following the Fight Club Rule, but is slightly less smelly than static Service Locator.
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IUnityContainer container) {
this.accounts = container.ResolveAll<IAccount>();
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
//Registration is pretty clean in this case
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
container.RegisterInstance<IUnityContainer>(container);
If your concern is having a dependency on Unity throughout your application, you can combine the service locator with a facade to hide the IOC implementation. In this way, you do not create a dependency on Unity in your application, only on having something that can resolve types for you.
For example:
public interface IContainer
{
void Register<TAbstraction,TImplementation>();
void RegisterThis<T>(T instance);
T Get<T>();
}
public static class Container
{
static readonly IContainer container;
public static InitializeWith(IContainer containerImplementation)
{
container = containerImplementation;
}
public static void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public static void RegisterThis<T>(T instance)
{
container.RegisterThis<T>(instance);
}
public static T Get<T>()
{
return container.Get<T>();
}
}
Now all you need is an IContainer implementation for your IOC container of choice.
public class UnityContainerImplementation : IContainer
{
IUnityContainer container;
public UnityContainerImplementation(IUnityContainer container)
{
this.container = container;
}
public void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public void RegisterThis<T>(T instance)
{
container.RegisterInstance<T>(instance);
}
public T Get<T>()
{
return container.Resolve<T>();
}
}
Now you have a service locator that is a facade for IOC services, and can configure your service locator to use Unity or any other IOC container. The rest of the application has no dependency on the IOC implementation.
To configure your service locator:
IUnityContainer unityContainer = new UnityContainer();
UnityContainerImplementation containerImpl = new UnityContainerImplementation(unityContainer);
Container.InitializeWith(containerImpl);
For testing, you can create a stub of IContainer that returns whatever you want, and initialize Container with that.

Categories