Alexander Beletsky's development blog

My profession is engineering

Inside ASP.NET MVC: IDependencyResolver - Service locator in MVC

All types inside ASP.NET MVC3 framework are being resolved by IDependencyResolver. The design goal of this interface is to provide flexibility and decrease coupling between components.

namespace System.Web.Mvc {
    using System.Collections.Generic;

    public interface IDependencyResolver {
        object GetService(Type serviceType);
        IEnumerable<object> GetServices(Type serviceType);
    }
}

If take a look into the code you will definitely smell the Service Locator pattern. Indeed, IDependencyResolver is pure service locator.

DependencyResolver as IDependencyResolver holder

IDependencyResolver instance is being accessed through the DependencyResolver class.

public class DependencyResolver {
 // Static accessors

 private static DependencyResolver _instance = new DependencyResolver();

 public static IDependencyResolver Current {
  get {
   return _instance.InnerCurrent;
  }
 }

It is a singleton class, current instance is being accessed through Current property. The default implementation is DefaultDependencyResolver.

// Instance implementation (for testing purposes)

private IDependencyResolver _current = new DefaultDependencyResolver();

Even if the comment says (for testing purposes) that class is used in real code. Let’s take a look on that.

private class DefaultDependencyResolver : IDependencyResolver {
 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")]
 public object GetService(Type serviceType) {
  try {
   return Activator.CreateInstance(serviceType);
  }
  catch {
   return null;
  }
 }

 public IEnumerable<object> GetServices(Type serviceType) {
  return Enumerable.Empty<object>();
 }
}

As you might see, it is extremely simple. It just tries to resolve the type by Activator class. If the type could be resolved it just returns it’s instance, otherwise just return null. The GetServices method just returns empty enumerable.

Substituting default DependencyResolver

As I said above, the main design goal of DependencyResolver is to provide flexibility. By flexibility I mean just easy way to substitute any type with own implementation. Say you want to change the ControllerFactory or ModelBinder or what ever you like. Everything is possible just by overriding IDependencyResolver.

I’ve seen one common misconception about MVC3, that it is contains IoC container inside it. It is not true, but it expose the interface which really much suites interfaces of famous IoC containers. To do not have a strict rules and force developers to use one type of IoC, ASP.NET MVC developers created a facility by which you can integrate yours IoC of choice. Let’s have a look how to do that.

DependencyResolver contains the number of setters to substitute the instance.

public static void SetResolver(IDependencyResolver resolver) {
 _instance.InnerSetResolver(resolver);
}

public static void SetResolver(object commonServiceLocator) {
 _instance.InnerSetResolver(commonServiceLocator);
}

[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types.")]
public static void SetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices) {
 _instance.InnerSetResolver(getService, getServices);
}

As example of implementation here my very dummy dependency resolver.

namespace MvcForDebug2.Infrastructure {
    public class DummyDependencyResolver : IDependencyResolver {
        public object GetService(Type serviceType) {
            if (serviceType.Equals(typeof(IControllerFactory))) {
                return new DummyControllerFactory();
            }

            return null;
        }

        public IEnumerable<object> GetServices(Type serviceType) {
            return null;
        }
    }
}

Finally, in global.asx.cs you need to set it up.

protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();

 RegisterGlobalFilters(GlobalFilters.Filters);
 RegisterRoutes(RouteTable.Routes);

 DependencyResolver.SetResolver(new DummyDependencyResolver());
 //ControllerBuilder.Current.SetControllerFactory(new DummyControllerFactory());
}

Conclusions

IDependencyResolver is a powerful feature of ASP.NET MVC3. It is used to create all internal MVC types, so by overriding it you can override default behavior of many framework aspects. Typically you should not have any complex code in GetService and GetServices methods, but instead just delegation of call to IoC container.