1

Situation: I have multiple MVC areas and i want to setup unity IOC (UnityConfig.cs) in each area which should work independently.

Problem: The IOC container overwrites itself.

Question: how can i make the container unique per area? or How to add RegisterType items to an existing container (in the root web for example) from an Area?

Thanks in advance,

Mogica

Area1

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<DbContext, CmsContext>(new HierarchicalLifetimeManager());
    container.RegisterType<IUnitOfWork, UnitOfWork>();
    container.RegisterType<ISiteRepository, SiteRepository>();
    container.RegisterType<IPageRepository, PageRepository>();
    container.RegisterType<IViewRepository, ViewRepository>();
}

Area2

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<IPostRepository, PostRepository>();
}

Area3

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<IJobRepository, JobRepository>();
}

1 Answer 1

3

If you want isolate parts of your application by giving each isolated part a different container instance (by effectively making each area a module), you will have to intercept the creation of controllers and dispatch that to the container of the correct area.

Intercepting the creation of controllers is done by implementing a custom IControllerFactory. Such implementation might look like this:

public class PerAreaControllerFactoryComposite : IControllerFactory {
    private IDictionary<string, IControllerFactory> areaControllerFactories;

    public PerAreaControllerFactoryComposite(
        IDictionary<string, IControllerFactory> areaControllerFactories) {
        this.areaControllerFactories = areaControllerFactories;
    }

    public IController CreateController(RequestContext requestContext,
        string controllerName) {
        var factory = this.FindFactory(requestContext);
        var controller = factory.CreateController(requestContext, controllerName);
        HttpContext.Current.Items["Factory_" + controller.GetType().Name] = factory;

        return controller;
    }

    public void ReleaseController(IController controller) {
        var factory = HttpContext.Current.Items["Factory_" + controller.GetType().Name]
            as IControllerFactory;

        factory.ReleaseController(controller);
    }

    public SessionStateBehavior GetControllerSessionBehavior(
        RequestContext requestContext, string controllerName) {
        var factory = this.FindFactory(requestContext);
        return factory.GetControllerSessionBehavior(requestContext, controllerName);
    }

    private IControllerFactory FindFactory(RequestContext context) {
        string area = context.RouteData.DataTokens["area"].ToString();
        return this.areaControllerFactories[area];
    }
}

This IControllerFactory implementation accepts a dictionary with a collection of IControllerFactory implementations, where the key of the dictionary is the name of the area. When CreateController is called, it will determine the current area and forward the call to the IControllerFactory implementation for that area.

You can create this implementation as follows:

var factory = new PerAreaControllerFactoryComposite(new Dictionary
{
    { "Area1", new UnityControllerFactory(area1Container) },
    { "Area2", new UnityControllerFactory(area2Container) },
    { "Area3", new UnityControllerFactory(area3Container) },
});

ControllerBuilder.Current.SetControllerFactory(factory);

The Unity integration package probably lacks a UnityControllerFactory, but creating one will be trivial (you can simply derive from DefaultControllerFactory).

Do note that running isolated modules in one application comes with extra development overhead, so the size of the application must justify it. Having multiple container instances complicates your registration so it is typically preferable to not do this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.