Sitecore pipelines & commands using IoC containers

Ever wondered how to resolve your command / pipeline entry from your IoC container? One of the more common arguments I have seen for the Service Locator (anti) pattern is for exactly this reason, and it’s completely avoidable. This approach works perfectly well with the likes of Castle Windsor, Autofac, Unity or even Agnostic IoC. This also provides the added bonus of being able to unit test your pipelines, which in my humble opinion is possibly where it is needed most. It also allows you to utilise constructor injection in Sitecore Pipelines (which I have heard from seasoned Sitecore developers can’t be done 😉 ).

In this post I describe how to give control of your dependencies on pipeline & commands to your IoC container of choice using Sitecore factories.

Below, we find an example class to create a Sitecore factory class. This class allows Sitecore to initialise it’s pipeline / command entries in a standard way. In doing so, it provides a hook to allow you to simply resolve the type from an IoC container rather than using an Activator.CreateInstance call.

    using System;
    using System.Diagnostics.CodeAnalysis;

    using Sitecore.Reflection;

    public class ContainerFactory : IFactory
    {
        private readonly IContainerManager containerManager;

        public ContainerFactory() : this(new LocatorContainerManager()) // service locate an appropriate container
        {
        }

        public ContainerFactory(IContainerManager containerManager)
        {
            this.containerManager = containerManager;
        }

        public object GetObject(string identifier)
        {
            Type type = Type.GetType(identifier);
            return this.containerManager.Resolve(type);
        }
    }

To use this in Sitecore thanks to its extensible configuration API, we need to patch it in. In order to use this to resolve pipelines in your code you just need to add the factory to your configuration node for the pipeline.

  <sitecore>
    <events>
      <event name="item:saved">
        <handler factory="ContainerFactory" ref="MyApp.MyHandler, MyApp" method="MyMethod">
          <database>master</database>
        </handler>
      </event>
    </events>
    <pipelines>
      <MyPipeline>
        <processor type="1" factory="ContainerFactory" ref="MyApp.MyProcessor, MyApp" />
      </MyPipeline>
    </pipelines>
    <factories>
      <factory id="ContainerFactory" type="MyApp.ContainerFactory"></factory>
    </factories>
  </sitecore>

As you can see, we just use the factory attribute to tell the entry how it is to be resolved. Simple as that.

Advertisements

19 thoughts on “Sitecore pipelines & commands using IoC containers

  1. Pingback: Be careful with Sitecore pipeline processors lifecycle | ctor.io

  2. Ok, one more question. I’ve got this working in pipelines and events. Now, for the first time, I need to use this in a command, specifically in the Page Editor. I’ve set up the command in the Core database and when I don’t use my IoC factory, the command works. When I move it all over to use IoC, and set up my config like this:

    then I get an error. When I click the command in the page editor, MyFactory.GetObject() is never called. And nothing happens. When I look in the console in Chrome, I see an error: “mycommand is not defined.”

    Have you used this with a command before? Any ideas what I’m doing wrong here?

  3. Have you managed to get this working for injecting a processor into the pipeline?

    I’m running 7.2 and following this article, https://www.sitecore.net/learn/blogs/technical-blogs/john-west-sitecore-blog/posts/2015/01/controller-constructor-injection-with-the-sitecore-aspnet-cms.aspx, trying the use the ContainerFactory to resolve dependencies passed to the InitializeControllerFactory processor in the pipeline.

    This is throwing “Sitecore.Exceptions.InvalidStructureException: No group node for sub node: initialize”

    [InvalidStructureException: No group node for sub node: initialize]
    Sitecore.Xml.XmlUtil.GetAncestor(String ancestorName, XmlNode subNode, Boolean assert) +228
    Sitecore.Pipelines.CorePipelineFactory.GetObjectFromName(String objectName, XmlNode processorNode) +104
    Sitecore.Pipelines.CoreProcessor.GetMethod(Object[] parameters) +65
    Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +351
    Sitecore.Nexus.Web.HttpModule.Application_Start() +172
    Sitecore.Nexus.Web.HttpModule.Init(HttpApplication app) +516
    System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +530
    System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +304
    System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +404
    System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +475

  4. Pingback: Sitecore Pipelines and Unity | Himadri's Technical Blog

  5. Seems like the “factory” attribute doesn’t work for Sitecore 8.0. Sitecore just ignores it. Fortunately there’s “factoryMethod” attribute that works fine for me.

  6. Pingback: No group node for sub node | Coffee First based .NET and Sitecore Dev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s