的ControllerFactory特定区域便携 [英] ControllerFactory for specific portable area
问题描述
我的主要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屋!