我花了一些时间看看Phil Haack关于分组控制器的文章非常有趣.
目前我正在试图弄清楚是否可以使用相同的想法为我正在开发的项目创建插件/模块化架构.
所以我的问题是:菲尔的文章中的区域是否可能分为多个项目?
我可以看到名称空间会自行解决,但我担心最终会在正确的地方出现.是否可以使用构建规则进行整理?
假设在单个解决方案中有多个项目可以实现上述目标,那么是否有人对使用单独的解决方案和编码到预定义的接口集合的最佳方法有任何想法?从区域移动到插件.
我有一些插件架构的经验,但没有大量的经验,所以这方面的任何指导都会有用.
几周前我做了一个概念验证,在那里我放了一个完整的堆栈组件:一个模型类,一个控制器类及其相关的DLL视图,添加/调整了一个检索视图的VirtualPathProvider类的例子他们会适当地解决DLL中的问题.
最后,我只是将DLL放入一个经过适当配置的MVC应用程序中,就像它从一开始就是MVC应用程序的一部分一样.我推了一下它,它与5个这样的小迷你MVC插件一起使用就好了.显然,你必须在将它们随机播放时观察你的引用和配置依赖关系,但它确实有效.
这个练习的目的是为我正在为客户构建的基于MVC的平台的插件功能.有一组核心控制器和视图,在站点的每个实例中都有更多可选的控制器和视图.我们将把这些可选位转换为这些模块化DLL插件.到现在为止还挺好.
我在我的网站上编写了我的原型概述和ASP.NET MVC插件的示例解决方案.
编辑:4年后,我一直在使用插件做很多ASP.NET MVC应用程序,不再使用我上面描述的方法.此时,我通过MEF运行所有插件,并且根本不将控制器放入插件中.相反,我制作通用控制器,使用路由信息选择MEF插件,并将工作交给插件,等等.只是想我会添加,因为这个答案得到了很大的帮助.
我实际上正在开发一个可扩展性框架,以便在ASP.NET MVC之上使用.我的可扩展性框架基于着名的Ioc容器:Structuremap.
我试图实现的用例很简单:创建一个应该具有一些可以为每个客户扩展的基本功能的应用程序(=多租户).应该只托管一个应用程序实例,但可以为每个客户调整此实例,而无需对核心网站进行任何更改.
我受到了Ayende Rahien写的关于多重性的文章的启发:http://ayende.com/Blog/archive/2008/08/16/Multi-Tenancy--Approaches-and-Applicability.aspx 另一个灵感来源是Eric Evans关于领域驱动设计的书.My Extensibility框架基于存储库模式和根聚合的概念.为了能够使用该框架,托管应用程序应该围绕存储库和域对象构建.控制器,存储库或域对象在运行时由ExtensionFactory绑定.
插件只是一个包含控制器或存储库或域对象的组件,它们遵循特定的命名约定.命名约定很简单,每个类都应该以customerID为前缀,例如:AdventureworksHomeController.
要扩展应用程序,请将插件程序集复制到应用程序的扩展文件夹中.当用户请求客户根文件夹下的页面时,例如:http://multitenant-site.com/[ customerID ] /[ controller] /[ action] 框架检查是否有该特定客户的插件并实例化自定义插件类,否则它加载默认值一次.自定义类可以是控制器 - 存储库或域对象.此方法可以在各个级别(从数据库到UI)扩展应用程序,通过域模型,存储库.
如果要扩展某些现有功能,可以创建一个包含核心应用程序子类的插件.当您要创建全新的功能时,可以在插件中添加新的控制器.当请求相应的url时,这些控制器将由MVC框架加载.如果要扩展UI,可以在扩展文件夹中创建新视图,并通过新的或子类控制器引用视图.要修改现有行为,可以创建新的存储库或域对象或对现有的子类进行子类.框架职责是确定应为特定客户加载哪个控制器/存储库/域对象.
我建议看看structuremap(http://structuremap.sourceforge.net/Default.htm),特别是在Registry DSL功能http://structuremap.sourceforge.net/RegistryDSL.htm上.
这是我在应用程序启动时使用的代码,用于注册所有插件控制器/存储库或域对象:
protected void ScanControllersAndRepositoriesFromPath(string path) { this.Scan(o => { o.AssembliesFromPath(path); o.AddAllTypesOf().NameBy(type => type.Name.Replace("Controller", "")); o.AddAllTypesOf ().NameBy(type => type.Name.Replace("Repository", "")); o.AddAllTypesOf ().NameBy(type => type.Name.Replace("DomainFactory", "")); }); }
我还使用继承自System.Web.MVC的ExtensionFactory.DefaultControllerFactory.该工厂负责加载扩展对象(控制器/注册表或域对象).您可以通过在Global.asax文件中启动时注册它们来插入您自己的工厂:
protected void Application_Start() { ControllerBuilder.Current.SetControllerFactory( new ExtensionControllerFactory() ); }
可以在以下网址找到此框架作为完整运营的示例网站:http://code.google.com/p/multimvc /