ControllerFactory для конкретной переносимой области - PullRequest
6 голосов
/ 18 марта 2011

Мое основное составное приложение ASP.NET MVC использует глобальный контейнер Unity для регистрации типов. Приложение устанавливает фабрику контроллеров для использования этого глобального контейнера. Я хотел бы реорганизовать это так, чтобы каждая из моих переносимых областей использовала свой собственный дочерний контейнер Unity, чтобы разные области могли реализовывать интерфейсы различными способами. Кажется, что мне нужно иметь разные ControllerFactory для каждой области. Как мне это сделать, учитывая, что следующее устанавливает фабрику для всех?

ControllerBuilder.Current
    .SetControllerFactory(/* controller factory with global unity container */);

Ответы [ 2 ]

11 голосов
/ 20 марта 2011

Вы можете использовать MasterControllerFactory, который содержит все реализации IControllerFactory для каждой области и знает, какая фабрика может построить какую RequestContext. Это фактически позволяет вам выбрать другую ControllerFactory для любого варианта, а не только по области. Вот как это работает:

Все реализации фабрики контроллера области должны реализовывать IFilteredControllerFactory вместо IControllerFactory. Вот оно:

public interface IFilteredControllerFactory:IControllerFactory
{
    bool CanHandle(RequestContext requestContext);
}  

Пример реализации, которая фильтрует по имени области, выглядит следующим образом:

public class Area51ControllerFactory:IFilteredControllerFactory
{
    public bool CanHandle(RequestContext requestContext)
    {
        return requestContext.RouteData.DataTokens["area"].ToString().ToLowerInvariant() == "area51";
    }
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        // create a controller...
    }

    public void ReleaseController(IController controller)
    {
        // release the controller...
    }

}

Тогда вам нужен MasterControllerFactory, который выглядит следующим образом:

public class MasterControllerFactory : DefaultControllerFactory
{
    private readonly List<IFilteredControllerFactory> _slaveFactories;
    public MasterControllerFactory()
    {
        _slaveFactories = new List<IFilteredControllerFactory>();
    }
    public void RegisterFactory(IFilteredControllerFactory slaveFactory)
    {
        if(slaveFactory!=null && !_slaveFactories.Contains(slaveFactory))
        {
            _slaveFactories.Add(slaveFactory);
        }
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var factory = _slaveFactories.FirstOrDefault(x => x.CanHandle(requestContext));
        if(factory!=null)
        {
            return factory.CreateController(requestContext, controllerName);
        }
        return base.CreateController(requestContext, controllerName);
    }

    public override void ReleaseController(IController controller)
    {
        bool released = false;
        if (controller is Controller)
        {
            var requestContext = ((Controller) controller).ControllerContext.RequestContext;
            var factory = _slaveFactories.FirstOrDefault(x => x.CanHandle(requestContext));
            if (factory != null)
            {
                factory.ReleaseController(controller);
                released = true;
            }
        }
        if(!released)base.ReleaseController(controller);
    }
}

В Application_Start вашего global.asax вам все равно нужно все настроить, но это просто.

var masterControllerFactory = new MasterControllerFactory();
masterControllerFactory.Register(new Area51ControllerFactory());
ControllerBuilder.Current.SetControllerFactory(masterControllerFactory);

Очевидно, вы можете настроить это несколькими способами, чтобы лучше всего работать с вашим стилем кодирования и архитектурой приложения.

0 голосов
/ 18 марта 2011

Я не думаю, что вы можете иметь разные фабрики для каждой области, но вы можете на своей фабрике поместить контроллер в другой контейнер, в зависимости от области.Я думаю , но не уверен, что вы можете найти свою область в методе CreateController вашей фабрики, сделав запрос:

requestContext.RouteData.DataTokens["area"];

, где requestContext передается CreateController в качестве параметра.

...