获取与 MVC 项目关联的区域
有没有办法获取 MVC 项目中区域的名称?
我可以想到以下几种方法:
a) 如果我有源代码,我可以浏览项目文件夹结构并枚举 Areas 文件夹下的文件夹。但这并不能保证所有文件夹都代表区域,除非我还枚举了每个子文件夹下的 Controllers 和 Views 文件夹。正如您所知,这种方法很糟糕。
b) 从二进制文件中,我可以枚举符合条件 RootNamespaceOfProject.Areas.*
的所有命名空间。
或者,我确信有一种更优雅的方式。 ASP.NET MVC框架中必须有一些字典来保存所有区域的记录。
其次,MVC 框架中是否也有代表一个区域的程序化构造?我好像找不到一个只有四种与区域相关的构造:
1. AreaRegistration
2. AreaRegistrationContext
3. IRouteWithArea
4. AreaHelpers (an internal class)
如果有一个,是否可以枚举该区域内的所有控制器?
已编辑
我刚刚注意到文件夹 \Windows\Microsoft.NET\Framework\v4.xx\Temporary ASP.NET Files\ 中有一个名为 MVC-AreaRegistrationTypeCache.xml
的文件根\随机生成的哈希1\随机生成的哈希2\UserCache。
该文件夹有两个文件:
a) MVC-AreaRegistrationTypeCache.xml:该文件包含计算机上所有程序集中具有区域的所有区域的列表。
b) MVC-ControllerTypeCache.xml:此文件列出了程序集区域内的控制器。
现在,唯一需要了解的是是否有某种编程方式可以让 MVC 框架读取这些文件并告诉我二进制文件中是否存在某个区域。
我认为 AreaRegistration
类可能就是这样的。进一步探索...
Is there a way I can get the names of the areas in an MVC project?
Here's a few ways I can think of:
a) If I had the source, I could browse through the project folder structure and enumerate the folders under the Areas folder. But that wouldn't guarantee all the folders represent areas unless I also enumerated the Controllers and Views folder under each of the sub-folders. This approach, as you can tell, sucks.
b) From the binary, I could enumerate all namespaces that match the criteria RootNamespaceOfProject.Areas.*
.
Or, I am sure there's a more elegant way. There must be some dictionary in the ASP.NET MVC framework that keeps a record of all the areas.
Secondly, is there also a programmatic construct in the MVC framework that represents an area? I can't seem to find one. There are only four constructs that are related to areas:
1. AreaRegistration
2. AreaRegistrationContext
3. IRouteWithArea
4. AreaHelpers (an internal class)
If there were one, would it be possible, say, to enumerate all the controllers within that area?
Edited
I just noticed that there's this file called MVC-AreaRegistrationTypeCache.xml
in the folder \Windows\Microsoft.NET\Framework\v4.x.x\Temporary ASP.NET Files\root\RandomlyGeneratedHash1\RandomlyGeneratedHash2\UserCache.
This folder has two files:
a) MVC-AreaRegistrationTypeCache.xml: This file has the list of all the areas in all the assemblies on the machine that have areas.
b) MVC-ControllerTypeCache.xml: This file lists the controllers within the areas of the assemblies.
Now, the only thing to find out is if there's some programmatic way to have the MVC framework read these files and tell me if a certain area exists in a binary.
I am thinking that the AreaRegistration
class might be the one. Exploring it further...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
似乎您能够检索项目中注册的路线的唯一方法是枚举继承 AreaRegistration 的类型的项目,似乎没有任何跟踪当前注册区域的私有或公共对象。
接下来是长解释...
这里要记住的一个障碍是区域只不过是任意字符串和名称空间列表之间的耦合。当一个区域被注册时,它只是使用一些可通过唯一的“区域”DataToken 识别的新规则来扩展应用程序的路由集合。
如果您查看注册区域的过程,您必须继承 System.Web.Mvc.AreaRegistration 并覆盖 RegisterArea()。 RegisterArea() 接收一个 AreaRegistrationContext ,它定义区域名称、路由集合和对象状态,但如果您观察实现 RegisterArea() 的格式,它会返回 void 并且不执行任何操作来保留上下文对象。更重要的是,如果您查看在 RegisterArea() 被触发之前运行的代码(Reflector),您可以看到传递给 RegisterArea() 的 AreaRegistrationContext 对象永远不会被永久跟踪。
如您所见,调用静态方法 RegisterAllAreas()调用内部
RegisterAllAreas(RouteCollection paths, IBuildManager buildManager, object state)
,然后调用内部CreateContextAndRegister(RouteCollection paths, object state)
,后者创建 AreaRegistrationContext 并传递它到RegisterArea()
。据我所知,在任何时候,为每个区域创建的 AreaRegistrationContext 都不会永久存储。
It would seem that the only way you will be able to retrieve the routes registered in your project is by enumerating the project for types which inherit AreaRegistration, there does not appear to be any object private or public which tracks currently registered areas.
Long explanation follows...
One hurdle to keep in mind here is that areas are little more than a coupling between an arbitrary string and a list of namespaces. When an area is registered it is merely extending the route collection for the application with some new rules identifiable by a unique "area" DataToken.
If you look at the process for registering an area, you must inherit from System.Web.Mvc.AreaRegistration and override RegisterArea(). RegisterArea() receives an AreaRegistrationContext which defines an area name, route collection and object state, but if you observe the format for implementing RegisterArea(), it returns void and does nothing to preserve the context object. What's more, if you look at the code which runs before RegisterArea() is fired (Reflector), you can see that the AreaRegistrationContext object which is passed to RegisterArea() is never permanently tracked.
As you can see, a call to the static method RegisterAllAreas() invokes the internal
RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
, which then calls the internalCreateContextAndRegister(RouteCollection routes, object state)
, which creates the AreaRegistrationContext and passes it toRegisterArea()
.As far as I can tell, never, at any point, is the AreaRegistrationContext created for each area stored permanently.
您可以执行 MVC 正在执行的操作,迭代所有引用的程序集并查找从
AreaRegistration
继承的类。然后您只需获取AreaRegistration.AreaName
即可。我计划这样做是使用 Twitter Bootstrap 构建我的顶级导航栏。
You could do what MVC is doing, iterate all the referenced assemblies and look for classes that inherit from
AreaRegistration
. Then you can simply get theAreaRegistration.AreaName
.I'm planning on doing this to build my top-level navbar using Twitter Bootstrap.
该线程有助于找到答案,但这里没有人明确发布它。这是我的想法,但请注意,您可能需要根据所有区域是否都在同一个程序集中进行调整。
This thread was helpful in finding the answer, but nobody here posted it explicitly. Here is what I came up with, but do note you may need to adjust it depending on whether all of your areas are in the same assembly.