Tuesday, March 4, 2014

Dependency injection in Sitecore event handlers

Following my previous article about Dependency injection in Sitecore custom commands, I think it is only appropriate to continue with something similar for Sitecore event handlers. And when I say similar I mean very similar - in fact reading this article after having read the previous one may induce some sense of deja vu :-) To learn more about Sitecore events visit Using Events.

This article assumes an understanding of Sitecore events and the concept of dependency injection. The purpose is to show how to use dependency injection in Sitecore events.

The normal way of creating an event handler for a Sitecore event is to create a handler class with an EventHandler delegate, i.e. a method with the EventHandler signature, and then add some config to Sitecore's <events> section defining where to find the event handler implementation, so that Sitecore can instantiate the event handler and trigger the delegate when the event occurs.

The problem with this approach is that nowadays it is common to use dependency injection in software solutions, and letting Sitecore take care of creating instances of your custom code means that you loose the possibility of injecting the needed dependencies. Luckily there is also a way out of this morass.

Sitecore has created a class called Event, which is used for subscribing, unsubscribing, and raising events. The good news is that it is available for use.

So here is a suggestion on how to use it to obtain dependency injection in Sitecore events. It is based on using Autofac as IoC container.

First, create a base class for your event handlers:

namespace TestApp.Events
{
  public abstract class BaseEventHandler
  {
    public string FullName { get; private set; }

    protected BaseEventHandler(string fullName)
    {
      FullName = fullName;
    }

    public abstract void OnEvent(object sender, System.EventArgs args);
  }
}
This base class defines the EventHandler delegate method signature that all derived event handler classes must implement, but it also has one property, FullName, for holding the event name for registration purposes.

Next, create your event handler inheriting from BaseEventHandler like this:
namespace TestApp.Events
{
  public class MyEventHandler : BaseEventHandler
  {
    private readonly IMyDependency _myDependency;

    public MyEventHandler(string fullName, IMyDependency myDependency)
      : base(fullName)
    {
      _myDependency = myDependency;
    }

    public override void OnEvent(object sender, System.EventArgs args)
    {
      // event handler implementation
    }
  }
}
As you can see we inject a dependency in the constructor. The constructor furthermore calls the base constructor to set the event name.

Now, create a class for registering events using the Sitecore Event class:
namespace TestApp.Events
{
  public static class EventConfigurator
  {
    public static void Configure(System.Collections.Generic.IEnumerable<BaseEventHandler> eventHandlers)
    {
      foreach (var eventHandler in eventHandlers)
      {
        Sitecore.Events.Event.Subscribe(eventHandler.FullName, eventHandler.OnEvent);
      }
    }
  }
}
The Configure method takes a collection of BaseEventHandler objects (our event handler instances), then uses Subscribe method on the Event class to subscribe the events.

That is basically all the pieces we need. We just have to fit everything together in our bootstrapper (the place where all the dependencies are set up using the IoC container). This could look something like this:
...
var builder = new ContainerBuilder();

builder.RegisterType<MyDependency>().As<IMyDependency>().InstancePerLifetimeScope();

builder.RegisterType<MyEventHandler>().As<BaseEventHandler>().WithParameter("fullName", "mynamespance:mycategory:myevent").InstancePerLifetimeScope();

var rootContainer = builder.Build();

var eventHandlers = rootContainer.Resolve<IEnumerable<BaseEventHandler>>();
EventConfigurator.Configure(eventHandlers);
...
So we just register dependencies as usual. The new thing is that we now register our event handlers in code, instead of using a Sitecore config file. And then we call our EventConfigurator with a collection of instances of all our event handlers.

That's it. Plain and simple :-)

Update:
Please note that since the event handlers are resolved only once (at app startup), any injected dependencies are effectively singletons.

Saturday, March 1, 2014

Dependency injection in custom Sitecore commands

Custom commands are probably one of the more ignored features in Sitecore, but they can be quite powerful. They could for example be used for insert options on templates, thereby allowing code to run on creation of content items. To learn more about commands (or specifically Command Templates) visit "Sitecore CMS 6.0 or later Data Definition Cookbook" chapter 4.

This article assumes an understanding of Command Templates and the concept of dependency injection. The purpose is to show how to use dependency injection in custom commands in Sitecore.

The normal way of creating a Sitecore custom command is to create a class inheriting from Sitecore.Shell.Framework.Commands.Command, overriding the Execute method, and then adding some config to Sitecore's <commands> section defining where to find the command implementation, so that Sitecore can instantiate the command.

The problem with this approach is that nowadays it is common to use dependency injection in software solutions, and letting Sitecore take care of creating instances of your custom code means that you loose the possibility of injecting the needed dependencies. Luckily there is a way out of this morass.

Sitecore has created something called a CommandManager, which is used for registering, instantiating and looking up commands. The good news is that it is available for use.

So here is a suggestion on how to use it to obtain dependency injection in custom commands. It is based on using Autofac as IoC container.

First, create a base class for your commands:

namespace TestApp.Commands
{
public abstract class BaseCommand : Sitecore.Shell.Framework.Commands.Command
{
public string FullName { get; private set; }

protected BaseCommand(string fullName)
{
FullName = fullName;
}
}
}
Basically, we will just use this base class to "label" our custom commands, but it also has one property, FullName, for holding the command name for registration purposes.

Next, create your custom command inheriting from BaseCommand like this:
namespace TestApp.Commands
{
public class MyCommand : BaseCommand
{
private readonly IMyDependency _myDependency;

public MyCommand(string fullName, IMyDependency myDependency)
: base(fullName)
{
_myDependency = myDependency;
}

public override void Execute(Sitecore.Shell.Framework.Commands.CommandContext context)
{
// command implementation
}
}
}
As you can see we inject a dependency in the constructor. The constructor furthermore calls the base constructor to set the command name.

Now, create a class for registering custom commands using the Sitecore CommandManager:
namespace TestApp.Commands
{
public static class CommandConfigurator
{
public static void Configure(IEnumerable<BaseCommand> commands)
{
foreach (var command in commands)
{
Sitecore.Shell.Framework.Commands.CommandManager.RegisterCommand(command.FullName, command);
}
}
}
}
The Configure method takes a collection of BaseCommand objects (our custom command instances), then uses RegisterCommand method on the CommandManager to register the commands.

That is basically all the pieces we need. We just have to fit everything together in our bootstrapper (the place where all the dependencies are set up using the IoC container). This could look something like this:
...
var builder = new ContainerBuilder();

builder.RegisterType<MyDependency>().As<IMyDependency>().InstancePerLifetimeScope();

builder.RegisterType<MyCommand>().As<BaseCommand>().WithParameter("fullName", "mynamespance:mycategory:mycommand").InstancePerLifetimeScope();

var rootContainer = builder.Build();

var commands = rootContainer.Resolve<IEnumerable<BaseCommand>>();
CommandConfigurator.Configure(commands);
...
So we just register dependencies as usual. The new thing is that we now register our custom commands in code, instead of using a Sitecore config file. And then we call our CommandConfigurator with a collection of instances of all our custom commands.

That's it. Plain and simple :-)