使用 MEF 构建具有 n 层松散耦合的 MVC ASP.NET 应用程序
Posted
技术标签:
【中文标题】使用 MEF 构建具有 n 层松散耦合的 MVC ASP.NET 应用程序【英文标题】:Building MVC ASP.NET app with n-tier loose coupling using MEF 【发布时间】:2011-09-01 09:09:52 【问题描述】:我有 MVC 项目。模型、控制器和视图都有自己的项目,因此有 3 个 dll。我还有一个 IFACADE、IBUSINESS 和 IDATALAYER 接口(dll),在 FACADE、BUSINESS 和 DATACCESS DLLS 中有具体实现。 如何使用 MEF 将它们连接在一起?
【问题讨论】:
【参考方案1】:我的建议是在您的系统中定义第一个可扩展点,在什么层或您希望允许第三方开发人员扩展或完全替换的组件。您必须定义可扩展性的起点和终点。
这是您在开始开发之前必须做出的设计决定。您可能稍后可以更改,但它会花费您更多的时间,并且您必须进行很多更改。在您定义它之后,一切都会变得容易得多。
尝试定义契约(接口),因为 MEF 中的契约取代了典型应用程序的紧密耦合。 MEF 在运行时使用协定来匹配 Import 和 Export 组件。
如果您有 ex 的存储库。 ProductRepository 有一些方法,然后创建一个包含这些方法的接口 IProductRepository,然后用 export 属性标记 ProductRepository,如下所示:
public interface IProductRepository
IEnumerable<Product> GetProducts(Expression<Func<Product, bool>> query);
[Export(typeof(IProductRepository))]
public class ProductRepository : IProductRepository
public IEnumerable<Product> GetProducts(Expression<Func<Product, bool>> query)
throw new NotImplementedException();
为了争论,假设您有这样的产品服务:
public interface IProductService
IEnumerable<Product> GetLatestProducts(int items);
[Export(typeof(IProductService))]
public class ProductService : IProductService
private IProductRepository _repository;
[ImportingConstructor]
public ProductService(IProductRepository repository)
this._repository = repository;
public IEnumerable<Product> GetLatestProducts(int items)
return _repository.GetProducts(p => p.DateCreated == DateTime.Today).OrderByDescending(p => p.DateCreated).Take(items);
通过使用 Export 属性标记您的存储库,您可以让您的服务通过 MEF 导入相同的存储库。如您所见,我们将工作委托给 MEF CompositionContainer 以向 ProductService 提供 ProductRepository 的实例……我们通过构造函数注入使用依赖注入来注入此实例。
然后在您的 MVC 控制器上应用相同的原则,但现在您导入的是 ProductService 而不是 ProductRepository ......像这样:
[Export(typeof(IController))]
[ExportMetadata("Name","Product")]
public class ProductController : Controller
private IProductService _service;
[ImportingConstructor]
public ProductController(IProductService service)
_service = service;
public ActionResult LatestProducts()
var model = _service.GetLatestProducts(3);
return View(model);
通过导出控制器,您可以随时将控制器放置在同一个程序集中或单独的程序集中。如您所见,我向控制器添加了另一个属性 [ExportMetadata("Name","Product")]。这用于在查询组合容器时决定哪个控制器退出组合容器。
现在您接下来需要做的是从某个目录创建匹配器 => 组合容器:TypeCalog、DirectoryCatalog、AssemblyCatalog 或 AggregateCatalog。您告诉目录加载程序集的位置。你可以在codeplex阅读更多内容
现在您需要一种方法来让您的控制器脱离 CompositionContainer。在 MVC 中可以执行此操作的地方是 ControllerFactory。您必须创建一个自定义 ControllerFactory(通过继承 DefaultControllerFactory 或实现 IControllerFactory 接口)。然后在控制器工厂中查询组合容器并找到请求的控制器。
你大概可以理解,组合的过程是从控制器工厂开始的:ProductController导入ProductService,ProductService导入ProductRepository。 MEF 组合容器遍历依赖关系图并满足这些导入。
【讨论】:
感谢 f 的回答。您是否有可以共享的示例应用程序。提前致谢 订阅这个博客,在接下来的几天里我打算发布类似的东西 - phalanx.spartansoft.org/author/m-shaqiri以上是关于使用 MEF 构建具有 n 层松散耦合的 MVC ASP.NET 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
.Net框架搭建之2SQL Server MEF依赖注入 MVC Repository框架