我们在 ASP.NET MVC 中使用了大量的 MEF,尽管其中大部分位于控制器级别以下,因为在我们的较低级别模块中使用 MEF 插件来检查权限和验证数据。
然而,我们也对我们的控制器使用了一种更可组合的方法。视图更棘手,但我们实际上完全消除了常规 ASP.NET MVC 视图的使用,并将我们的 Razor 视图存储在数据库中的片段中。然后,我们的控制器在运行时向模板引擎请求视图并将 ContentResult 呈现给响应,而不是返回 View("Viewname") 等。
我们的 MEF 插件都带有标识符属性,可以让我们在运行时进行级联覆盖,以确定应该将哪个插件/类用于给定目的。最简单的演示示例是,如果您考虑一个具有共同基础但部署到 50 多个实现的应用程序,每个实现都可以选择覆盖核心功能。
因此,您可能有类似 IUserController 的东西,其中包含“登录”、“注销”等方法。
除了该实际功能之外,我们还将向名为“SiteId”的界面添加一个只读 GUID 属性。然后,每个实现都会硬编码它打算用于的 SiteId。对于核心代码中的“默认”实现,它将返回“Guid.Empty”。
然后,当我们调用 MEF 并查找要使用的 IUserController 的实现时,我们会将所有这些实现 ImportMany 到一个 List 中,然后使用 LINQ 查询属性以确定要使用哪个:
var _currentUserController = _availableUserControllers.FirstOrDefault(
c=>c.SiteId == AppSettings.SiteId);
if(_currentUserController == null){
//There is no site-specific override
_currentUserController = _availableUserControllers.FirstOrDefault(
c=>c.SiteId == Guid.Empty);
}
要使用控制器执行此操作,最好的办法是查看 Web 上基于 MEF 的控制器工厂的一些实现。
然而,就像我说的那样,我们几乎所有这些都是在较低的级别上进行的,并且让我们的模块或控制器进行这种查找以确定要运行哪些插件。