的ControllerFactory特定区域便携 [英] ControllerFactory for specific portable area

查看:206
本文介绍了的ControllerFactory特定区域便携的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的主要ASP.NET MVC的复合应用程序使用一个全球性的统一容器注册类型。该应用程序设置控制器出厂到使用这种全球集装箱。我想这个重构,使得我的便携式领域的每一个利用它自己的孩子团结的容器,使不同区域可以有不同的方式实现的接口。好像我需要有每个地区不同的ControllerFactory。我将如何实现这个目标,鉴于以下设置工厂呢?

  ControllerBuilder.Current
    .SetControllerFactory(/ *控制器工厂与全球统一的容器* /);


解决方案

您可以使用 MasterControllerFactory 包含所有的 IControllerFactory 每个区域实现,并且知道哪些工厂可以建立其 RequestContext的。这实际上可以让你选择不同的ControllerFactory任何变化,而不仅仅是区域。下面是它如何工作的:

所有区域控制器工厂实现必须实现 IFilteredControllerFactory 而不是 IControllerFactory 的。在这里,它是:

  public接口IFilteredControllerFactory:IControllerFactory
{
    布尔CanHandle(RequestContext的RequestContext的);
}

这滤波器根据区域名称实现的一个例子是这样的:

 公共类Area51ControllerFactory:IFilteredControllerFactory
{
    公共BOOL CanHandle(RequestContext的的RequestContext)
    {
        返回requestContext.RouteData.DataTokens [区]的ToString()ToLowerInvariant()==51区。
    }
    公众一个IController CreateController(RequestContext的的RequestContext,串controllerName)
    {
        //创建一个控制器...
    }    公共无效ReleaseController(一个IController控制器)
    {
        //释放控制器...
    }}

然后,你需要在 MasterControllerFactory ,它看起来像这样:

 公共类MasterControllerFactory:DefaultControllerFactory
{
    私人只读表< IFilteredControllerFactory> _slaveFactories;
    公共MasterControllerFactory()
    {
        _slaveFactories =新的List< IFilteredControllerFactory>();
    }
    公共无效RegisterFactory(IFilteredControllerFactory slaveFactory)
    {
        如果(slaveFactory = NULL&放大器;!&安培;!_slaveFactories.Contains(slaveFactory))
        {
            _slaveFactories.Add(slaveFactory);
        }
    }    公众覆盖一个IController CreateController(RequestContext的的RequestContext,串controllerName)
    {
        VAR厂= _slaveFactories.FirstOrDefault(X => x.CanHandle(RequestContext的));
        如果(出厂!= NULL)
        {
            返回factory.CreateController(RequestContext的,controllerName);
        }
        返回base.CreateController(RequestContext的,controllerName);
    }    公共覆盖无效ReleaseController(一个IController控制器)
    {
        布尔发布= FALSE;
        如果(控制器控制器)
        {
            VAR的RequestContext =((控制器)控制器).ControllerContext.RequestContext;
            VAR厂= _slaveFactories.FirstOrDefault(X => x.CanHandle(RequestContext的));
            如果(出厂!= NULL)
            {
                factory.ReleaseController(控制器);
                发布= TRUE;
            }
        }
        如果(发布!)base.ReleaseController(控制器);
    }
}

在的的Application_Start你的的Global.asax ,你仍然需要设置好一切,但是这很容易。

  VAR masterControllerFactory =新MasterControllerFactory();
masterControllerFactory.Register(新Area51ControllerFactory());
ControllerBuilder.Current.SetControllerFactory(masterControllerFactory);

当然,你可以在此调整通过多种方式来实现您的编码风格和应用架构。

My main ASP.NET MVC composite application uses a global Unity container to register types. The app sets the controller factory up to use this global container. I would like to refactor this such that each one of my portable areas leverages it's own child Unity container, so that different areas can implement interfaces in varying ways. It seems like I would need to have a different ControllerFactory per area. How would I accomplish that, given that the following sets the factory for all?

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

解决方案

You can use a MasterControllerFactory that contains all the IControllerFactory implementations for each area, and knows which factory can build which RequestContext. This actually allows you to select a different ControllerFactory for any variation, not just by area. Here's how it works:

All of the area controller factory implementations must implement IFilteredControllerFactory instead of IControllerFactory. Here it is:

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

An example of an implementation that filters based on the area name looks like this:

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...
    }

}

Then you need the MasterControllerFactory, which looks like this:

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);
    }
}

In the Application_Start of your global.asax you still need to set everything up, but that's easy.

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

Obviously, you can tweak this a number of ways to work best with your coding style and application architecture.

这篇关于的ControllerFactory特定区域便携的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆