在 MVC4 中,您可以创建自定义控制器工厂以在创建控制器实例时捕获它们。您可以将其用作单个合成点,而不必在每个控制器中都这样做。
通过继承来创建自定义控制器工厂System.Web.Mvc.DefaultControllerFactory
。覆盖该GetControllerInstance
方法并让基本函数为您创建控制器。现在你可以让你的依赖注入引擎组成控制器。
public class AreaControllerFactory : DefaultControllerFactory
{
// We use a controller factory to hook into the MVC pipeline in order to get a reference to controllers
// as they are being created. We inherit from the default controller factory because we do not want to
// have to locate the appropriate controllers ourself (we only want a reference to it). Once we have a
// reference, we simply hand the controller off for composition.
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
IController controller = base.GetControllerInstance(requestContext, controllerType); // create the controller
if (controller != null)
{
var container = ...; //construct your composition container
container.ComposeParts(controller); //compose your controller
}
return controller;
}
}
Application_Start
在Global.asax.cs
. _
var controllerFactory = new AreaControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
为了按区域过滤组合对象,我为每个区域构建了一个自定义的全局区域组件字典(例如区域名称字典、适用类型列表)。
// NOTE:ComposablePartCatalog is MEF specific, change as needed
internal static class AreaComponents
{
/// <summary>
/// A list of Area name, catalog pairs.
/// Each Area can provide a custom list of components to import from.
/// </summary>
internal static readonly Dictionary<string, ComposablePartCatalog> AreaCompositionCatalogs =
new Dictionary<string, ComposablePartCatalog>();
}
RegisterArea
在每个区域的AreaRegistration
实现方法中填充字典。
public class XAreaRegistration : AreaRegistration
{
public override void RegisterArea(AreaRegistrationContext context)
{
/* ... Standard route logic ... */
// Set up an MEF catalog with Area components
var xCatalog = new AssemblyCatalog(
typeof(MyPluginsNamespace.ArbitraryTypeToLookupAssembly).Assembly);
AreaComponents.AreaCompositionCatalogs["X"] = xCatalog;
}
}
在为给定控制器构建组合容器时,使用此字典在我的自定义控制器工厂中选择适当的组合对象子集。
// Capture current area name
System.Web.HttpContextBase contextBase = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);
System.Web.Routing.RouteData routeData = System.Web.Routing.RouteTable.Routes.GetRouteData(contextBase);
object areaObject = routeData.DataTokens["area"];
string areaName = areaObject as string ?? string.Empty;
// Create a composition container specific to this area
ComposablePartCatalog areaCatalog =
AreaMefComponents.AreaCompositionCatalogs.ContainsKey(areaName) ?
AreaMefComponents.AreaCompositionCatalogs[areaName] : null;
var container = new CompositionContainer(areaCatalog);