ASP.NET MVC 仿真 - (3)从Assemblies中找出所有的Controller

时间:2022-05-19 16:11:45

上次已经获取了Controller的名字,想通过Controller的名字来实例化一个Controller,该怎么办呢?

MVC框架的做法是从相关的Assembly中找出所有符合Controller特性的类型。将它们放入一个叫MVC-ControllerTypeCache.xml的缓存中。这次重点我们来仿真一下如何从所有先关的Assembly中找出Controller类型,缓存机制到以后性能优化再详细叙述。


IController.cs:

namespace MvcFake.mvc
{
public interface IController
{
}
}

HomeController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MvcFake.mvc;

namespace MvcFake.Controllers
{
public class HomeController : IController
{

}
}

MvcHandler.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Collections;
using System.IO;
using System.Web.Compilation;
using System.Reflection;

namespace MvcFake.mvc
{
public class MvcHandler : IHttpHandler
{
public bool IsReusable { get; set; }
private RequestContext RequestContext { get; set; }

public MvcHandler(RequestContext requestContext)
{
RequestContext = requestContext;
}


internal static bool IsControllerType(Type t)
{
return
t != null &&
t.IsPublic &&
t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
!t.IsAbstract &&
typeof(IController).IsAssignableFrom(t);
}

private static bool TypeIsPublicClass(Type type)
{
return (type != null && type.IsPublic && type.IsClass && !type.IsAbstract);
}

private static IEnumerable<Type> FilterTypesInAssemblies()
{
IEnumerable<Type> typesSoFar = Type.EmptyTypes;

ICollection assemblies = BuildManager.GetReferencedAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] typesInAsm;
try
{
typesInAsm = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
typesInAsm = ex.Types;
}
typesSoFar = typesSoFar.Concat(typesInAsm);
}
return typesSoFar.Where(type => TypeIsPublicClass(type) && IsControllerType(type));
}

public void ProcessRequest(HttpContext context)
{
string controllerName = RequestContext.RouteData.GetRequiredString("controller");

context.Response.Write("Controller Name: " + controllerName);

IEnumerable<Type> types = FilterTypesInAssemblies();

foreach (var type in types)
{
context.Response.Write("<br>Controller Type Name: " + type.ToString());
}
}
}
}

项目结构:

ASP.NET MVC 仿真 - (3)从Assemblies中找出所有的Controller

运行程序:

ASP.NET MVC 仿真 - (3)从Assemblies中找出所有的Controller

从运行的结果可以看到,我们已经成功地找到Assembly中的Controller了。