动态扩展应用程序的function?
我最近遇到了一种在使用ASP.NET MVC3 / 4时开发可插拔应用程序模块的方法,我喜欢这种方法的简单性。 目前,我的应用程序结构如下:
因此,任何想要为我的应用程序开发扩展的人都遵循上述教程中的方法,并创建一个保留在Areas
文件夹中的扩展。 我想,当添加新Areas
(创建为新项目)时,会创建.pdb
文件并将其放在bin
目录中。 我的问题是:
- 如何将
Areas
分配为可插拔模块? - 如何更改以下代码,以便当有人将新
Area
放入bin
文件夹时,应用程序会自动选择它并创建链接? 插件作者应该怎么做才能启用它?
在我的_Layout.cshtml
(全局共享布局)中,我执行以下操作来构建链接:
- @Html.ActionLink("Area1", "Index", "Area1", new { Area = "Area1" }, null)
- @Html.ActionLink("Area2", "Index", "Area2", new { Area = "Area2" }, null)
- @Html.ActionLink("Area3", "Index", "Area3", new { Area = "Area3" }, null)
为简单起见,假设区域名称是唯一的。 有关如何做到这一点的任何建议?
如何将Areas分配为可插拔模块?
不要在托管Web应用程序中创建区域,而是创建单独的项目,编译以分隔dll。 将dll复制到您要使用它的任何Web应用程序。 请记住将所有静态文件设置为“EmbeddedResource”。
如何更改以下代码,以便当有人将新区域放入bin文件夹时,应用程序会自动选择它并创建链接? 插件作者应该怎么做才能启用它?
您可以使用MvcContrib PortableAreaRegistration的“总线”将便携式区域中的消息,命令发送给“总线”上的任何人。 这可以是托管网络应用程序,或理论上独立区域可以相互发送消息。
在github上创建了两个粗略但function性的演示代码:
MVC3版本:
https://github.com/AkosLukacs/PluggablePortableAreas
MVC4 RC版本:
https://github.com/AkosLukacs/PluggablePortableAreasMVC4
首先,您定义一条可以传递所需信息的消息。 只是一个具有一些属性的POCO(PluggablePortableAreas.Common \ RegisterAreaMessage.cs):
public class RegisterAreaMessage : IEventMessage { public string LinkText { get; private set; } public string AreaName { get; private set; } public string ControllerName { get; private set; } public string ActionName { get; private set; } //... }
为该消息类型创建一个处理程序(PluggablePortableAreas.Common \ RegisterAreaEventHandler.cs):
public class RegisterAreaEventHandler : MessageHandler{}
在这种情况下,MessageHandler只是将收到的消息添加到静态ConcurrentBag
。 如果您愿意,可以使用DI,但希望保持简单。
您可以从便携式区域发送消息(Areas \ DemoArea1 \ Areas \ Demo1 \ Demo1AreaRegistration.cs):
//the portable area sends a message to the 'bus' bus.Send(new RegisterAreaMessage("Link to the Demo area", AreaName, DefaultController, DefaultAction));
通过迭代消息集合(PluggablePortableAreas.Web \ Views \ Shared_Layout.cshtml)显示动态添加的链接:
@foreach(var sor in PluggablePortableAreas.Common.RegisterAreaEventHandler.RegisteredAreas) { @Html.ActionLink(sor.LinkText, sor.ActionName, sor.ControllerName, new{Area=sor.AreaName}, null) }
还有一件事需要注意:使用“完全限定”的区域名称。 如果未明确指定区域名称,则MVC假定它是当前区域。 没有区域没有问题,但第二个将指向"/path_to_your_app/CurrentArea/Home"
而不是"/path_to_your_app/Home"
。
@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null) @Html.ActionLink("I don't work from the portable area!", "Index", "Home")
还有一件事需要注意!
VS中的开发服务器感觉有点“不稳定”,有时便携式区域无法加载。 在完整的IIS中可靠地运行…
你在做什么看起来与MVCContrib的便携式领域非常相似。
他们使用消息/应用程序总线模式在Web元素上动态添加新的小部件。 通过reflection发现MessageHandler,并将每条消息传递给所有消息。 因此,在您的情况下,插件作者应该只为标准消息实现处理程序(比如注册全局菜单链接)。
嵌入了便携式区域的资源,因此只能在bin文件夹中删除一个dll。 为了自动提取并在你的应用程序中使用它,你必须通过FileSystemWatcher观察bin文件夹并重启你的应用程序(没有其他方法可以将新的.dll加载到asp.net应用程序中的AppDomain中我认为)。
您也可以使用ASP.NET 4中的BuildManagerfunction从其他文件夹加载.dll。 这里有更多有用的信息。
这看起来类似于Orchard CMS的模块。
看看他们的Gallery ……模块作为Nuget包发布,包含整个模块项目。
嗨,你可以在nopcommerce项目中寻找相当不错的插件架构。
看看这个教程,我认为它会对你有很大的帮助。