February 17, 2012

ASP.NET MVC 3 Dependency Injection with StructureMap

StructureMap implementations of IDependencyResolver, FilterAttributeFilterProvider and IModelBinderProvider for dependency injection in ASP.NET MVC 3.

StructureMapDependencyResolver

public class StructureMapDependencyResolver : IDependencyResolver {
    private readonly IContainer container;

    public StructureMapDependencyResolver(IContainer container) {
        this.container = container;
    }

    public object GetService(Type serviceType) {

        if (serviceType == null)
            return null;

        return serviceType.IsAbstract || serviceType.IsInterface
                 ? container.TryGetInstance(serviceType)
                 : container.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        return container.GetAllInstances(serviceType).Cast<object>();
    }
}

StructureMapFilterProvider (for property injection)

public class StructureMapFilterProvider : FilterAttributeFilterProvider {

    private readonly IContainer container;

    public StructureMapFilterProvider(IContainer container) {
        this.container = container;
    }

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
        var filters = base.GetFilters(controllerContext, actionDescriptor);

        foreach (var filter in filters)
            container.BuildUp(filter.Instance);

        return filters;
    }
}

StructureMapModelBinderProvider

public class StructureMapModelBinderProvider : IModelBinderProvider {
    private readonly IContainer container;

    public StructureMapModelBinderProvider(IContainer container) {
        this.container = container;
    }
    
    public IModelBinder GetBinder(Type modelType) {
        var mappings = container.GetInstance<ModelBinderMappingDictionary>();
        if (mappings != null && mappings.ContainsKey(modelType))
            return container.GetInstance(mappings[modelType]) as IModelBinder;

        return null;
    }
}

public class ModelBinderMappingDictionary : Dictionary<Type, Type> {
    public void Add<TKey, TModelBinder>() where TKey : class where TModelBinder : IModelBinder {
        this.Add(typeof(TKey), typeof(TModelBinder));
    }
}

Registering the providers

public class MyRegistry : Registry
{
	public MyRegistry()
	{
        For<ModelBinderMappingDictionary>().Use(GetModelBinders());
        For<IModelBinderProvider>().Use<StructureMapModelBinderProvider>();
        For<IFilterProvider>().Use<StructureMapFilterProvider>();
    }

    private static ModelBinderMappingDictionary GetModelBinders()
    {
        var binders = new ModelBinderMappingDictionary();
        binders.Add<Site, SiteModelBinder>();
		binders.Add<PortfolioSettings, PortfolioSettingsModelBinder>();
		binders.Add<BlogSettings, BlogSettingsModelBinder>();
        binders.Add<CustomizationSettings, CustomizationSettingsModelBinder>();
        return binders;
    }
}

© 2022 Ben Foster