Controller类型的解析()
激活目标Controller对象的前提是能够正确解析出Controller类型对于DefaultControllerFactory来说用于解析目标Controller类型的辅助信息包括通过与当前请求匹配的路由对象生成的RouteData(其中包含Controller的名称和命名空间)和包含在当前ControllerBuilder中的命名空间很多读者可能首先想到的是通过Controller名称得到对应的类型并通过命名空间组成Controller类型的全名最后遍历所有程序集并以此名称去加载相应的类型即可
这貌似是一个不错的解决方案实际上则完全行不通不要忘了作为请求地址URL一部分的Controller名称是不区分大小写的而类型名称则是大小写敏感的此外不论是注册路由时指定的命名空间还是当前ControllerBuilder的默认命名空间有可能包含统配符(*)由于我们不能通过给定的Controller名称和命名空间得到Controller的真实类型名称自然就不可能通过名称去解析Controller的类型了
ASPNET MVC的Controller激活系统则反其道而行之它先遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到所有引用程序集通过反射的方式得到定义在它们中的所有实现了接口IController的类型最后通过Controller的名称和命名空间作为匹配条件去选择对应的Controller类型
实例演示创建一个自定义ControllerFactory模拟Controller默认激活机制(S)
为了让读者对默认采用的Controller激活机制尤其是Controller类型的解析机制有一个深刻的认识通过一个自定义的ControllerFactory来模拟其中的实现由于采用反射的方式来创建Controller对象所以将该自定义ControllerFactory起名为ReflectedControllerFactory
public class ReflectedControllerFactory : IControllerFactory
{
//其他成员
private static List<Type> controllerTypes;
static ReflectedControllerFactory()
{
controllerTypes = new List<Type>()
foreach (Assembly assembly in BuildManagerGetReferencedAssemblies())
{
controllerTypesAddRange(assemblyGetTypes()Where(
type => typeof(IController)IsAssignableFrom(type)))
}
}
public IController CreateController(RequestContext requestContext
string controllerName)
{
Type controllerType = thisGetControllerType(requestContextRouteData
controllerName)
if (null == controllerType)
{
return null;
}
return (IController)ActivatorCreateInstance(controllerType)
}
[] []