MVC 3和MEF以及向主应用程序添加插件

Bab*_*loo 4 mef entity-framework-4 asp.net-mvc-3

我是MEF的新手,我真的很混乱!这里有很多有用的文章,在stackoverflow中有很多问题和答案.我下载了@ matthew-abbott在他的博客中上传的示例,但我不知道如何添加新的插件或扩展来扩展主Web应用程序,我的意思就像你在这里看到的那样.

编辑:我也使用实体框架,代码优先方法和工作单元为我的数据访问层应用程序,如果我的插件需要数据访问和(我的意思是插件本身模型)想要使用我创建的DAL ?正如您所知,每次模型更改时,DbContext都会抛出错误并告诉重新创建数据库,是否有任何方式或其他ORM动态接受扩展DAL?

Mat*_*ott 5

该特定示例显示了我们如何将MEF与MVC3的新集成,DependencyResolver后者为MVC架构内的各种扩展点提供服务定位机制.我的博客上还有一些其他文章详细介绍了有关可能的插件架构如何工作的更多信息,这些文章可在以下网址找到:

  1. 模块化ASP.NET MVC使用托管可扩展性框架(MEF),第一部分
  2. 模块化ASP.NET MVC使用托管可扩展性框架(MEF),第二部分
  3. 模块化ASP.NET MVC使用托管可扩展性框架(MEF),第三部分

还有很多精彩的文章,我的建议也是:

  1. ASP.NET MVC和 Maarten Balliauw 的Managed Extensibility Framework(MEF)
  2. Tim Roberts 用MEF定义Web范围的部件

MVC是一种非常灵活的体系结构,可以通过多种方式进行扩展,但由于ASP.NET应用程序在IIS中的运行方式,您需要非常仔细地考虑部分生命周期.例如,控制器只能用于一个请求,因此您可能需要确保控制器具有特定的控制权CreationPolicy.蒂姆罗伯特关于网络范围部分的文章是一篇特别好的读物.

希望这足以指出你正确的方向.

编辑:由于MEF提供的模块化特性,确保不同的图层分离是很重要的.您已指定使用实体框架,但实际情况是,EF应该只在您的数据层中使用.通常,MVC架构将促进域模型上的视图模型.为此,使用与存储库模式类似的东西定义可能很有用,例如这里是一个模拟UserRepository:

[Export(typeof(IUserRepository))]
public class UserRepository : IUserRepository
{
  public IEnumerable<UserViewModel> GetUsers() 
  {
    // Get values here from EF as domain models
    // And return them as view models?
  }
}
Run Code Online (Sandbox Code Playgroud)

我们可以导出并注入控制器:

[ExportController("User"), PartCreationPolicy(CreationPolicy.NonShared)]
public class UserController : Controller
{
  private readonly IUserRepository _repo;

  [ImportingConstructor]
  public UserController(IUserRepository repo)
  {
    if (repo == null)
      throw new ArgumentNullException("repo");

    _repo = repo;
  }

  public ActionResult Index()
  {
    var users = _repo.GetUsers();
    return View(users);
  }
}
Run Code Online (Sandbox Code Playgroud)

这只是一个非常简单的示例,但与许多IoC容器一样,MEF也支持依赖注入.只要零件提供合适的导出,就可以在合成时将其导入(通过属性注入或构造函数注入)到另一个零件中.

我的建议是反对将EF暴露给你的观点,因为这使得他们明确地依赖于它.通过注意分离并仅在正确的层上暴露正确的类型,您的架构将变得更加健壮,灵活和可测试,这使得维护它并更容易地更新它.作为另一个简单的例子,这是我们如何测试我们的控制器:

[Test]
public void UserController_CreatesViewResult_WithListOfUsers()
{
  var mock = new Mock<IUserRepository>();
  mock.Setup(m => m.GetUsers()).Returns(new[] { new UserViewModel { Name = "Matt" } });

  var controller = new UserController(mock.Object);

  var result = controller.Index();

  Assert.That(result is ViewResult);
  // Other assertions.
}
Run Code Online (Sandbox Code Playgroud)

因为我没有将EF紧密耦合到我的视图中,所以我的控制器更加可测试,我可以模拟一个合适的存储库并测试我需要的位置.

重要的是规划您的架构.