获取与MVC项目关联的区域

Wat*_* v2 6 asp.net-mvc-areas asp.net-mvc-2

有没有办法可以获得MVC项目中的区域名称?

以下是我能想到的几种方法:

a)如果我有源,我可以浏览项目文件夹结构并枚举Areas文件夹下的文件夹.但这并不能保证所有文件夹都代表区域,除非我还枚举了每个子文件夹下的Controllers and Views文件夹.你可以说,这种方法很糟糕.

b)从二进制文件中,我可以枚举符合条件的所有名称空间RootNamespaceOfProject.Areas.*.

或者,我确信这是一种更优雅的方式.ASP.NET MVC框架中必须有一些字典可以记录所有区域.

其次,MVC框架中是否还有一个代表一个区域的程序化构造?我好像找不到一个.只有四个区域相关的结构:

 1. AreaRegistration
 2. AreaRegistrationContext
 3. IRouteWithArea
 4. AreaHelpers (an internal class)
Run Code Online (Sandbox Code Playgroud)

如果有的话,那么是否有可能枚举该区域内的所有控制器?

编辑

我只是注意到MVC-AreaRegistrationTypeCache.xml在文件夹\ Windows\Microsoft.NET\Framework\v4.xx\Temporary ASP.NET Files\root\RandomlyGeneratedHash1\RandomlyGeneratedHash2\UserCache中调用了此文件.

该文件夹有两个文件:

a)MVC-AreaRegistrationTypeCache.xml:此文件包含计算机上具有区域的所有程序集中的所有区域的列表.

b)MVC-ControllerTypeCache.xml:该文件列出了程序集区域内的控制器.

现在,唯一要弄清楚的是,是否有一些编程方式让MVC框架读取这些文件并告诉我二进制文件中是否存在某个区域.

我在想这个AreaRegistration班可能就是那个.进一步探索......

Nat*_*lor 6

看起来您能够检索项目中注册的路径的唯一方法是枚举项目以继承AreaRegistration的类型,似乎没有任何私有或公共对象跟踪当前注册的区域.

很长的解释如下......

这里要记住的一个障碍是区域只不过是任意字符串和命名空间列表之间的耦合.当一个区域被注册时,它只是扩展了应用程序的路径集合,其中一些新规则可由唯一的"区域"DataToken识别.

如果查看注册区域的过程,则必须从System.Web.Mvc.AreaRegistration继承并覆盖RegisterArea().RegisterArea()接收一个AreaRegistrationContext,它定义了一个区域名称,路径集合和对象状态,但如果你观察到实现RegisterArea()的格式,它将返回void并且不会保留上下文对象.更重要的是,如果查看在触发RegisterArea()之前运行的代码(Reflector),您可以看到传递给RegisterArea()的AreaRegistrationContext对象永远不会被永久跟踪.

internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
{
    foreach (Type type in TypeCacheUtil.GetFilteredTypesFromAssemblies("MVC-AreaRegistrationTypeCache.xml", new Predicate<Type>(AreaRegistration.IsAreaRegistrationType), buildManager))
    {
        ((AreaRegistration) Activator.CreateInstance(type)).CreateContextAndRegister(routes, state);
    }
}

internal void CreateContextAndRegister(RouteCollection routes, object state)
{
    AreaRegistrationContext context = new AreaRegistrationContext(this.AreaName, routes, state);
    string str = base.GetType().Namespace;
    if (str != null)
    {
        context.Namespaces.Add(str + ".*");
    }
    this.RegisterArea(context);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,对静态方法RegisterAllAreas()的调用将调用internal RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state),然后内部调用internal CreateContextAndRegister(RouteCollection routes, object state),这将创建AreaRegistrationContext并将其传递给RegisterArea().

据我所知,在任何时候,永远不会为为每个永久存储区域创建的AreaRegistrationContext.