Category Archives: MEF

Using MEF in MVC to inject Controllers

After travelling for a year I was interest to see if MEF would work with MVC, and after some digging around I found it can.

***UPDATED****

Added a CastleWindsor example

With any MEF you’ll need a Composition Factory which in this case I’ll place in the MEF directory, but it can be in a different project if required.

public class CompositionContainerFactory
    {
        public CompositionContainer CreateContainer()
        {
            var path = HostingEnvironment.MapPath("~/bin");

            if (path == null) throw new Exception("Unable to find the path");

            var catalog = new DirectoryCatalog(path);

            return new CompositionContainer(catalog);
        }
    }

Now comes the interesting part, in MVC 3 Microsoft introduced the IDependencyResolver, which gets the services when needed.

So implementing the IDependencyResolver with MEF was a little trickier

public class MEFDependencyResolver : IDependencyResolver
    {
        private readonly CompositionContainer _container;

        public MEFDependencyResolver(CompositionContainer container)
        {
            if (container == null) throw new ArgumentNullException("container");

            _container = container;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType == null) throw new ArgumentNullException("serviceType");

            var name = AttributedModelServices.GetContractName(serviceType);

            return Enumerable.Any(_container.Catalog.Parts.SelectMany(part => part.ExportDefinitions), e => e.ContractName == name) ? _container.GetExportedValue<object>(name) : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            if (serviceType == null) throw new ArgumentNullException("serviceType");

            var name = AttributedModelServices.GetContractName(serviceType);

            return _container.GetExportedValues<object>(name);
        }
    }

The final step we will need to set the Dependency Resolver and this is done in the Application Start inside the Global.asax

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

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

            DependencyResolver.SetResolver(new MEFDependencyResolver(new CompositionContainerFactory().CreateContainer()));
        }

Now we are ready to use MEF inside of MVC.

To use MEF inside of MVC just attach the [Export] attribute to controller and then import the object you require, like this:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller
    {
        [ImportMany]
        private List<IAddress> Addresses { get; set; }

        public ActionResult Index()
        {
            return View(Addresses);
        }
    }

Make sure that the Part Creation Policy is Non-Shared otherwise you will only be able to visit the page once.

That is it, what more could you want, oh the code samples, which I have update to MVC 5.2

DI_Controller_Sample

CastleWindsorControllerInjection