A while back I covered off How to resolve Sitecore commands & pipelines from IoC. This I have used to great effect, to the point I can’t remember the last time I wrote a pipeline entry with a parameter-less constructor. This in itself has aided Unit Testing of pipelines so much I would consider it a must for all Sitecore development.
Recently however, I was faced with an instance where I now had to resolve two near identical items from my IoC container. In a regular .net application, I would simply use the named component functionality of the container and resolve at least one of my instances using such a name. In the case of Sitecore though – I didn’t have any more parameters to play with, and I mistakenly thought I only had the type name.
On closer investigation (and re-reading my own blog post) I noticed that it is simply an identifier NOT a fully qualified reference, meaning I could stuff in whatever I liked – down goes the shed door and cue the music…..
Below is a modified version of the same basic prisn is what I came up with for the original post, this time – you can now add a | (pipe) character and follow it with the name of the component from your IoC container. I have used Castle Windsor for this example, but the principle would work for pretty much any main stream IoC container (I may even write a version for Agnostic IoC ;).
using System; using Castle.Windsor; using Sitecore.Reflection; namespace MyNamespace { public class WindsorFactory : IFactory { private static readonly IWindsorContainer container = new WindsorContainer(); public static IWindsorContainer Container { get { return container; } } public object GetObject(string identifier) { if (identifier.IndexOf("|", StringComparison.InvariantCultureIgnoreCase) >= 0) { return GetNamed(identifier); } return GetDefault(identifier); } private static object GetDefault(string identifier) { Type type = Type.GetType(identifier); return Container.Resolve(type); } private static object GetNamed(string identifier) { var elems = identifier.Split('|'); string typeName = elems[0]; string name = elems[1]; Type type = Type.GetType(typeName); return Container.Resolve(name, type); } } }
Your pipeline entry then looks something like this, where ‘demo’ is the name of the component you have registered.
<processor mode="on" ref="MyNamespace.PrismDataProvider, MyNamespace|demo" factory="WindsorFactory"/>
Hope this helps
Additional Reading
Hi
Thanks for sharing this, itβs great π I used your implementation for events & pipelines during the Hackathon last weekend. Unfortunately this doesnβt seem to work for commands, as the CommandManager from Sitecore doesnβt allow the resolving classes over a factory. Did you find a solution for this? Or how do you resolve classes within a Sitecore command?
Greets,
Kevin
Thanks for the response Kevin – always good to know someone is reading π
Hmmm – I thought I had done one on commands in our current solution – will double check. I know the factory is not available for all configuration types.
Where it is not available, I tend to use a poor mans service locator implementation, something along the lines of (assuming the locator is called LocatorContainerManager)
public MyClass() : this(LocatorContainerManager.Resolve(), LocatorContainerManager.Resolve())
{
}
public MyClass(IDependency1 dependency1, IDependency2 dependency2)
{
// do something with dependencies here
}
This, whilst not a great solution, is one I can live with in terms of the following statements
– NO logic is ever added to the parameterless constructor
– The LocatorContainerManager is fully unit tested
This reduces the risk as much as we can realistically
I ended up in something similar (https://github.com/unic/SitecorePackMan/blob/master/src/Unic.PackMan.Core/DependencyInjection/ContainerFactory.cs), I used the container factory for the service locator pattern. I share your opinion that it isn’t great, but propably the best of the remaining solutions π
Yeah – that’s about right.
Off topic though, look up the speed of Ninject π
See this: IoC Battle 2015
It is my least favourite IoC container π
hehe, I knew why you wrote this directly after my comment π It was lazyness (because I know Ninject best), I would also use another container for the next upcoming projects π
Tbf – it was eye opening for me – I use Windsor by default cause of my ties to Glass Mapper – it was not the greatest either.