I started a new MVC4 project and wanted to use StructureMap for my IOC container of choice. I followed Phil’s post about wiring up dependency resolvers in mvc 4, but I kept getting the following error: “StructureMapDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator.
Parameter name: commonServiceLocator”
Took a little digging, but I found the CommonServiceLocator project from the Microsoft Patterns and Practice group. That project has a StructureMap implementation of the IServiceLocator interface for StructureMap. After I installed the CommonServiceLocator nuget, I was able to reference IServiceLocator in my code. Taking the code from the CommonServiceLocator implementation, I ended up with the following:
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Practices.ServiceLocation; | |
using StructureMap; | |
// This is part of MvcKickstart (https://nuget.org/packages/mvckickstart) | |
namespace MvcKickstart.Infrastructure | |
{ | |
/// <summary> | |
/// Wrapper for IDependencyScope, so that StructureMap plays nicely with built in mvc4 dependency resolution. | |
/// </summary> | |
public class StructureMapDependencyScope : ServiceLocatorImplBase | |
{ | |
protected readonly IContainer Container; | |
public StructureMapDependencyScope(IContainer container) | |
{ | |
if (container == null) | |
throw new ArgumentNullException("container"); | |
Container = container; | |
} | |
public new object GetService(Type serviceType) | |
{ | |
if (serviceType == null) | |
return null; | |
try | |
{ | |
return serviceType.IsAbstract || serviceType.IsInterface | |
? Container.TryGetInstance(serviceType) | |
: Container.GetInstance(serviceType); | |
} | |
catch | |
{ | |
return null; | |
} | |
} | |
/// <summary> | |
/// When implemented by inheriting classes, this method will do the actual work of resolving | |
/// the requested service instance. | |
/// </summary> | |
/// <param name="serviceType">Type of instance requested.</param> | |
/// <param name="key">Name of registered service you want. May be null.</param> | |
/// <returns> | |
/// The requested service instance. | |
/// </returns> | |
protected override object DoGetInstance(Type serviceType, string key) | |
{ | |
if (string.IsNullOrEmpty(key)) | |
{ | |
return GetService(serviceType); | |
} | |
return Container.TryGetInstance(serviceType, key); | |
} | |
/// <summary> | |
/// When implemented by inheriting classes, this method will do the actual work of | |
/// resolving all the requested service instances. | |
/// </summary> | |
/// <param name="serviceType">Type of service requested.</param> | |
/// <returns> | |
/// Sequence of service instance objects. | |
/// </returns> | |
protected override IEnumerable<object> DoGetAllInstances(Type serviceType) | |
{ | |
return Container.GetAllInstances(serviceType).Cast<object>(); | |
} | |
public IEnumerable<object> GetServices(Type serviceType) | |
{ | |
return Container.GetAllInstances(serviceType).Cast<object>(); | |
} | |
public void Dispose() | |
{ | |
Container.Dispose(); | |
} | |
} | |
} |
The following code will setup mvc to use structuremap as the dependency resolver. Add the webactivator nuget and toss the following file in your app_start folder:
using System.Web.Mvc; | |
using MvcKickstart.Infrastructure; | |
using StructureMap; | |
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.IocConfig), "PreStart", Order = -100)] | |
// This gets installed automatically with the MvcKickstart nuget (https://nuget.org/packages/mvckickstart) | |
namespace YourProject | |
{ | |
public static class IocConfig | |
{ | |
public static void PreStart() | |
{ | |
// If changes need to be made to IocRegistry, please subclass it and replace the following line | |
ObjectFactory.Initialize(x => x.AddRegistry(new IocRegistry(typeof(IocConfig).Assembly))); | |
DependencyResolver.SetResolver(new StructureMapDependencyScope(ObjectFactory.Container)); | |
} | |
} | |
} |
Hope this helps someone looking to do the same!
Your .Cast() extension method isn’t included here, or its namespace isn’t if it’s a built-in method.
Is there a working MVC4RC project you can point to that shows everything wired up, perhaps on Github?
Ah, using System.Linq; solves the Cast issue – http://msdn.microsoft.com/en-us/library/bb341406.aspx
And … of course you would also need the following line in global.cs : )
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(ObjectFactory.Container);
More recent code is available at: https://github.com/jgeurts/MvcKickstart/blob/master/Modules/MvcKickstart/Infrastructure/StructureMapDependencyResolver.cs
Also, the dependency resolver is set via WebActivator: https://github.com/jgeurts/MvcKickstart/blob/master/Modules/MvcKickstart/Nuget/App_Start/IocConfig.cs.pp
Installing the MVCKickstart nuget will auto wire all of that up for you.