Lately there has been a lot of discussions on twitter about using different third party frameworks for Inversion of Control using Dependency Injection in Sitecore solutions.
The arguments in these discussions can be almost religious, either for or against using a specific third party IoC framework. There are two extremes, on one side the developers who have just found IoC and now evangelize it wonders to the world and then on the other side we have developers who are either scared of IoC or have seen the hell it is when IoC frameworks are misused.
Personally I am somewhere in the middle of these extremes.
I too was a shirt and tie IoC evangelist for a short period of time. It was back when I first worked with Microsoft Unity some 5-6 years ago. It amazed me how IoC could be twisted to make your code really expressive and easy to read using only very few lines of code.
I quickly discovered the downside on large solutions, maintaining the code became a living nightmare. Stepping into specific implementations was not directly available and when you haven’t seen the code for some time or perhaps not written it yourself then you first had to untangle where the control over which types was. It was hard detective work almost each time something had to be changed. This is not good especially when the website does nothing more than some basic presentation.
Using third party IoC frameworks in general made our code less maintainable so we went away from using these if we did not have a very good reason at Pentia. Looking in the rear-view mirror it was a really tough and expensive experience we gained from our work with IoC containers but it is invaluable today.
Our approach now is to stay true to the Sitecore API and not introduce any third party frameworks for IoC except in the very rare cases where they really are the right tool for the job. And in these cases we keep them isolated and not as the foundation for the whole solution.
In hindsight it seems wrong to create a tight coupling with a third party framework and all your components just to gain loose coupling between your own components.
Loose coupling can be achieved in many other ways than using Inversion of Control and when you really need the pattern in a Sitecore solution, it is easy to implement without introducing any third party framework such as Ninject, Windsor, Unity, etc.
A basic IoC implementation that cover 29 out of 30 use cases can be achieved with very few lines of code using the Sitecore API.
These lines of code and the pattern is used everywhere in Sitecore. You know it from all Sitecore pipeline processors, providers, event handlers and so on in configuration and SheerUI command types in items.
Dependency Injection in raw form is no more than a container in which you can insert mappings between a name and a type.
In Sitecore there are two apparent ways of keeping a container that can contain your mappings, either using configuration or items (or mongo if you want an x-IoC container).
Using Sitecore configuration as DI container
For this simple example we use the Sitecore configuration section and Sitecore.Configuration namespace as our container.
To keep the example really simple lets consider the following simple configuration patch.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<typeMappings>
<mapping name="ProductRepository" type="LaubPlusCo.IoC.ProductRepository, LaubPlusCo.IoC"/>
</typeMappings>
</sitecore>
</configuration>
We have created a new custom configuration element in the Sitecore configuration section called typeMappings that contain a mapping called ProductRepository.
Now in code we can write a simple generic TypeResolver that look like this:
namespace LaubPlusCo.IoC
{
public class TypeResolver
{
public static T Resolve<T>(string typeName, object[] parameters = null)
{
var xpath = "typeMappings/mapping[@name='" + typeName + "']";
return (T)(parameters == null ?
Sitecore.Reflection.ReflectionUtil.CreateObjectFromConfig(xpath) :
Sitecore.Reflection.ReflectionUtil.CreateObjectFromConfig(xpath, parameters));
}
}
}
If we have an interface for our ProductRepository that look like this:
public interface IProductRepository
{
object Get();
void Set(object product);
}
Then we can resolve the implementation defined in configuration like this:
private IProductRepository productRepository = TypeResolver.Resolve<IProductRepository>("ProductRepository");
In this example we implicitly require the type defined in the ProductRepository to implement to IProductRepository interface. This could have been defined in a custom configuration element instead.
We instantiate the type using the class called ReflectionUtil from the Sitecore API. This class has been around at least since Sitecore 5.0.
ReflectionUtil.CreateObjectFromConfig calls a method on ReflectionUtil called CreateObject(..). This method can be used directly with the typename if you want to create objects from types written in text fields on items or similar (mongo).
Simple life time management
IoC frameworks typically have some degree of life time management so the mapped types are not instantiated each time they are resolved.
If you want your ProductRepository to be instantiated only once per process then you would wrap the resolving in a singleton pattern.
private static IProductRepository _productRepository;
public static IProductRepository ProductRepository
{
get { return _productRepository ?? (_productRepository = TypeResolver.Resolve<IProductRepository>("ProductRepository")); }
}
This is typically a really bad idea to do in a web application if you want it to scale since static is per process.
A common and good life time management requirement is to only instantiate the object once per thread or rather once per request in a web app.
This can be done like this:
private const string ProductRepositoryRequestCacheKey = "ProductRepository";
public static IProductRepository ProductRepository
{
get
{
var productRepository = (IProductRepository)HttpContext.Current.Items[ProductRepositoryRequestCacheKey];
if (productRepository != null)
return productRepository;
productRepository = TypeResolver.Resolve<IProductRepository>("ProductRepository");
HttpContext.Current.Items[ProductRepositoryRequestCacheKey] = productRepository;
return productRepository;
}
}
What about speed then? That is actually a really good question. I will do a speed comparison in a later blog post. I just had to get this one out quick to get me started on some blogging again. It has been some really slow two months for me.
What would you think is the fastest?
To resolve a type using MS Unity, Ninject or ReflectionUtil?
Share your thoughts in the comments below or tweet it @AndersLaub #SitecoreIoC
Comments
20 responses to “Simple IoC container using only the Sitecore API”
Great post, and a perfect summary of recent conversations I’ve been having.
As Sitecore developers, by definition we have a dependency on Sitecore. So we might as well make the most of its capabilities and reduce dependencies elsewhere.
Also, we’re often required to make use of the configuration factory to work with out-of-the-box features. So why not use it for everything?
Great post – I’ve always had similar thoughts – that we sometimes maybe depend too much on third-party apps. And I’m glad to see this post, because in our industry sometimes its taboo to mention that maybe writing something in-house as part of the solution being worked on is better than relying on a third-party solution, thereby creating a heavy dependency on them, because most people think its not a good sign to rewrite something that is already out there, tested and perfected over time – because “hey, why re-invent the wheel?”. I’m glad I’m not alone 🙂
On this note, what would you say about relying on third-party ORMs, such as glass mapper and such? I’ve personally found glass mapper very useful, but at the same time I feel that I’ve made my applications very dependent on it.
I like glass mapper a lot but it is a heavy dependency that dictates how your solution is built which is why I personally do not use introduce it in new solutions where I am the architect.
Using third party frameworks compared to writing your own functionality is a thin line. You always need to consider the Common Closure Principle that implicitly dictates that when using one class from a component you are re-using the component as a whole. Thus you are handing over the stability of your solution to code that you do not own. A component will never be more stable than the least stable of its dependencies. A Sitecore solution will never be more stable than Sitecore itself. A solution built on glass will never be more stable than glass. Glass will never be more stable than Windsor etc. The second half of the Stable Dependencies Principle comes into play.
So “re-inventing the wheel” by for example copy-pasting in selected parts of code from gitHub into your own framework layer component instead of taking a full pre-compiled assembly is not re-inventing the wheel, it is just common sense. Then you keep control of the stability of your solution.
On the other hand sometimes you really do not want to re-invent and let others do what they do best. This especially accounts for frameworks covering wide functionality such as ecommerce, search and similar.
Interesting article, in answer to your question, I think Ninject will definitely be slower, possibly / probably unity too. I would look at it against Autofac / SimpleInjector if its speed you would be interested in (simpleinjector’s performance is pretty close to the new() keyword.
It is also interesting that you consider Glass such a heavy dependency. I personally have found in use that it simply makes your code like regular .net, with the only true dependency being on a handful of Glass structures (ISitecoreContext / ISItecoreService, IGlassHtml and things like the Image / File classes it supplies). I think that it is also very very easy to abstract if you wish it to avoid it dictating how your solution is built (not that I think it dictates that much other than regular .net practice). Then barring your presentation code, the dependency for your own code is very minimal.
I tend to agree that you either need to write pure sitecore code and accept its lack of testability, or use an ORM like Glass and accept its pretty transparent mapping process.
Let me re-phrase the word heavy and instead call it a tight or strong dependency.
If Sitecore sends out an update that require glass to be updated too, then you are stuck until glass has been updated. Your whole solution is suddenly completely dependend on a third party api other than what Sitecore ships with.
The team behind glass are great and as it is right now this tight dependency only opens up for theoretical issues that will probably never occur.
Personally I have burned myself too many times on relying strongly on third party apis that for some reason stopped being maintained or introduced breaking changes preventing updates.
I guess any ORM would be a tight dependency, imho is the loosest of them which is one of the reasons I favour it.
At the minute with the current state of flux Sitecore has been in for a few versions, I don’t see it as a concern, and with Glass V4 there will be improvement on this front.
I believe on the IoC / DI front though – Sitecore (if they are going to) need to pick a container and stick to it, problems are starting to creep in with different versions of containers which is a source of frustration.
If Sitecore really need to ship with an IoC framework then I would like to know for what 🙂
But if it is the case then they should make an IoC abstraction layer so it is possible to swap in your own framework. That would in my opinion be the right solution.
I heard several times that ninject soon will be gone again, I really hope that they do not just replace it with another similar (but faster) framework.
Nice article, but damn you Anders I was just about to write an article about IoC!!!
As you know I was/am a big fan of IoC/dependency injection but it general it is over/mis-used and adds complexity where it is not needed.
Product Repository is a good example of where it typically can be used, as it’s a great tool to model the consumer and provider relationship, and loosely couple the consumer from the provider. Which makes it easy to change the provider, which seems to happen more often than you would think, typically starts off as product items in Sitecore, then moves to a PIM.
But I see a lot solution where it is misused and the majority classes are resolved/instantiated using IoC and or resolve is called 400000 times a request so it is impossible to find out what is constructed and the performance is very bad.
So the moral is to judge careful where to use it and ensure it is really required.
Thanks and damn you too Alan 🙂 You can write a post about the common misuses of IoC. I did not want to go there in this post then I never would have been done with it.
Anders, not sure I should open that flood gate as I might never close it again 🙂
Ninject is slower than everything, but cool name and features!
Sometimes I think it would be quicker to send an email to get the class resolved.
Interesting post indeed, reading through it and the comments it seems more about the use of third party dependencies. I suspect most developers, given the opportunity, would like to write everything from scratch and have complete control. This kind of opportunity is far from the real world of budgets and timelines. It is absolutely correct to state that by using something you haven’t created you are at the mercy of those third parties. The issue with taking this standing is where does it stop? The notion can become a vicious spiral to the point where you’re saying that because Sitecore depends on the .NET framework we shouldn’t use it! The use of third party software is one of trust. This trust comes from understanding the risk of using something someone else has created.
The example of being worried about Sitecore’s dependency on .NET is outlandish. We, as developers, know that .NET has been around a long time. It has a strong solid history and therefore we feel little risk in building applications on it. The same principle applies to using Sitecore over building your own proprietary CMS (sorry eXperience Platform ;)). Sitecore, as a third party, have built a product with lots of features which we don’t want to have to write and maintain ourselves. Doing our own would be time and money, which in the real world is a pipe dream.
At each level of dependency we make the judgement as to whether we trust that dependency. I would completely agree to be wary of using a framework called BobsAwesomeContainer.0.1.0.0 which was released last Tuesday. You’d opt for something like Castle Windsor because it has a proven track record. Also you then have to take into account adoption, people know Castle Windsor because it’s been around. Again time and money, using your own proprietary system means training costs, less familiarity. Clients get wary as they’re locked into something only you know about.
Real world = use trusted third party software
Pipe dream = let’s have control over everything
On a more specific note about IoC containers. I think inversion of control and dependency injection get mixed up and confused a lot. Inversion of control is decoupling your implementation from the systems that use them and being able to swap them without affecting other parts of your system. Dependency injection is about how you go about getting those dependencies into the other systems. I think the use of it is more about education and using it properly. I think you also mentioned about stepping into specific implementations. Isn’t the notion of using IoC that you shouldn’t need to know about how something works?
Good post though, certainly a good discussion/debate opener :)!
Hi Jason, thanks for your comment.
It has not been my intention to talk against using third party api’s and recommend developers writing everything from scratch. Not at all, that would be a waste of time and like you say a pipe-dream 🙂
As long as the Stable Dependency Principle is taken into consideration and as long as you have considered possible issues with code ownership/maintenance over time then third party apis for various tasks are great.
My main point with the post was to start a discussion about using third party DI frameworks in Sitecore solutions for inversion of control and discuss if these really are needed to get the job done.
The example code I made is as few or even fewer lines of code than what you need to hook in a typical DI framework. And then you own the (2-3 lines of) code and do not risk that the framework suddenly no longer is maintained etc.
So my point was to use the Sitecore API that is already the rock-foundation of your solution instead of using a new framework with its own maintenance track.
In my book Dependency Injection is an approach (a pattern) to achieve Inversion of Control.
You can use other patterns to achieve inversion of control and the different frameworks out there typically vary a bit in how the pattern is implemented. I was actually really afraid when I first wrote this post that it would end up in a terms discussion rather than getting my point out about ReflectionUtil 🙂
Oh my comment definitely went on a tangent, probably started on it in fact :)! I think after reading the post and the comments it felt like there was a notion of being scared of using third party code.
I get the simplicity and control factor of your example using Sitecore for dependency injection. I think you’ll soon get to the point where you say “why didn’t I just use an existing container?” I’d like to see constructor dependency injection just using the Sitecore API :P.
There’s a tonne of scenarios and options now with IoC/DI and I just think using a well known and mature enough container is the best approach.
Few, kept that comment much shorter :).
I think rather the opposite.
We’ve been using IoC / DI frameworks at Pentia, especially Unity for many many years, long before I saw anyone else using it in Sitecore solutions.
It is based on this experience that I today recommend to go in the other direction and not use DI frameworks as the foundation for your solution.
Today I am only using ReflectionUtil when creating modules where people really need to inject something or when I have a critical interface that I want to be able to mockup otherwise I do not use DI.
I do not dislike DI frameworks, they should just only be used when needed and not as part of or as an object relation mapper.
Sometimes it goes quite well using DI frameworks and if the solution is short lived then it does not matter that much.
It is over time that DI can almost obfuscate the codebase rather than making it easier to read.
Developers have a tendency to use DI for instantiating all classes, even those that never ever will change, thus removing all traces of dependencies among business objects. The dependencies are still there they are just soft dependencies that Visual Studio wont catch. In the end you’ll end up with a maintenance nightmare when business requirements changes.
If you notice the code I wrote you can pass in parameters to the constructor using ReflectionUtil.
So I do not see anything that I would be miss in regards to constructor injection or property injection for that manner in the few cases where I would actually like to use Dependency Injection at all.
I hope it makes sense what I am writing 🙂 It is based on many years of experience with DI containers.
Hi Anders,
Love this post!
I’m using this IoC solution for a Sitecore module that will be shipped to multiple vendors.
Because I don’t want the module to depend on an IoC framework of my choice, I prefer to use Sitecore’s own IoC and this works great.
With some additional tricks you can set it up in such way that a vendor can always implement their own IoC container if they like, without modification to any of our code.
Really valuable blog post, thank you very much!
Cheers,
Ruud
Thanks Ruud. I’m glad you liked it.
Hey Anders,
Just wanted to let you know we’ll be using your approach in Sitecore PowerShell Extensions to support Sitecore 7 & 8 with a single build. Really like it. Simple and straightforward!
Cheers,
Adam
Thanks Adam, I am glad to have contributed in some way to Powershell Extensions, love it.
Hi Anders! Would need little kick as I don’t see what I’m doing wrong. Taking in consideration your example, I don’t feel this is solving 29 of 30 cases. Thinking about just little bit more complex hierarchy of dependencies – which is nothing special – I can’t imagine how I use this approach. Not mention whole concept of configuring something what should stay safe-type in XML just by naming things. (Discovering typos in run-time is not amusing at all)
As my imagination is poor in this case, would you mind to share more complex case of this approach? Or any other recommendations? I’m quite new to SiteCore, I would know how to wire up things in MVC, or much better in vNext, but here, I’m pretty lost.
(Oh, and just another thing – shouldn’t be any IoC framework part of (in most cases) just top level project – usually web site project? I really don’t see any reason why to mix any IoC framework with my business logic, but in other hand, I have no problem to pick one of IoC framework and link it to my “main” project, which code is also taking care of resolution. In case of library shipment, either I let responsibility of wiring to final user or I prepare separate bootsrapper for user, depending on his/her preferences… simple as that.)