Changes to Dependency Injection in Sitecore 8.1

If you are reading this, chances are you have used some form of DI in your Sitecore Solution. If you’ve used some of the standard IoC containers in an MVC application, you’ve also most likely used a custom dependency resolver. Using Simpleinjector, you can make a pretty simple custom dependency resolver for Sitecore – see here. In pre Sitecore 8.1, you would also need to make a custom controller factory, so that you can resolve using your own container. There are number of posts that shows you how to build a cool custom controller factory:

What’s new in Sitecore 8.1?

Pre Sitecore 8.1, you had to make a custom controller factory because Sitecore by default did not use the DependencyResolver to create a controller instance. It was something like this:

 if (TypeHelper.LooksLikeTypeName(controllerName))
      {
        Type type = TypeHelper.GetType(controllerName);
        if (type != (Type) null)
          return TypeHelper.CreateObject(type);
      }
      return this.InnerFactory.CreateController(requestContext, controllerName);

In Sitecore 8.1, it uses the current DependencyResolver (as set by your application in App_Start) to create the controller instance – if it fails (i.e. didn’t find the concrete type in your container), then it still uses TypeHelper (Sitecore.Mvc.Helpers) to create the instance.

  if (TypeHelper.LooksLikeTypeName(controllerName))
      {
        Type type = TypeHelper.GetType(controllerName);
        if (type != (Type) null)
        {
          IController controller = DependencyResolver.Current.GetService(type) as IController ?? TypeHelper.CreateObject<IController>(type);
          if (controller != null)
            return controller;
        }
      }
   return this.InnerFactory.CreateController(requestContext, controllerName);

What this really means is that you don’t have to use your own custom controller factory anymore. You still need to use the fully qualified class name for the controller, though.

An update to how setup a custom dependency resolver

In my earlier post, I wrote about a simple custom dependency resolver using SimpleInjector. Steven van Deursen, one of the founders of SimpleInjector showed me a better way to do this, so that it would be compatible with upcoming changes in v3 and future changes. It involves wrapping your own implementation with a wrapper, so that creation of all instances are delegated to the SimpleInjectorDependencyResolver. Instead of implementing the GetService method yourself, you use the wrapper’s GetService method – this way, any updates done to SimpleInjector is seamless. So now, the class would look like this:

public class CustomDependencyResolver : IDependencyResolver
    {

        private IDependencyResolver wrappedResolver;

        public SitecoreDependencyResolver(IDependencyResolver wrappedResolver)
        {
            this.wrappedResolver = wrappedResolver;
        }



        public object GetService(Type serviceType)
        {
            try
            {
                return this.wrappedResolver.GetService(serviceType);
            }
            catch
            {
                return Sitecore.Mvc.Helpers.TypeHelper.CreateObject<IController>(serviceType, new object[0]);
            }

        }



        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this.wrappedResolver.GetServices(serviceType);
        }

    }

And then when setting the DependencyResolver in App_Start, it would look like this:

public static class SimpleInjectorInitializer
    {
        

        //Initialize the container and register it as MVC Dependency Resolver.
        public static void Initialize()
        {
            var container = new Container();
            
            InitializeContainer(container);

            container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
            
            container.Verify();

            DependencyResolver.SetResolver(new CustomDependencyResolver(new SimpleInjectorDependencyResolver(container)));

        }
     
        private static void InitializeContainer(Container container)
        {
            // Register your classes (anything other than the MVC controllers)
            // For instance:
            // container.Register<IUserRepository, SqlUserRepository>();
        }
    }

Happy Coding!

Advertisement

9 thoughts on “Changes to Dependency Injection in Sitecore 8.1

  1. Hi Mickey.

    I followed your implementation for SimpleInjector with Sitecore but when I try to use it with Glass Mapper I get the following error:

    —————————————————————————————
    The given key was not present in the dictionary.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.

    Source Error:

    Line 31: // container.Register();
    Line 32:
    Line 33: container.Register(() => new SitecoreContext());
    Line 34: container.Register();

    Source File: C:\Test\Source\TestSI\DependencyInjection\SimpleInjector\SimpleInjectorInitializer.cs Line: 33

    —————————————————————————————-

    Do you have any ideas why is not working when I try to get an instance of SitecoreContext?

    Thank you,
    Stefan

      1. Thanks for the replay. That Container.Register() at the end was from an old stack trace error (sorry for my bad copy-paste skill) but the error remains for the SitecoreContext. I will try to use the approach from that link but your implementation was more straight forward. Thanks again.

      2. I forgot. to answer your first question. It works if I don’t register the SitecoreContext. I tested with a simple Interface+Class and works just fine.

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 )

Connecting to %s