asp.net-mvc - 我们如何使用 ASP.NET MVC 4 和 MEF 2 支持模块化和可测试模式?

标签 asp.net-mvc asp.net-mvc-4 mef

我们尝试将 MEF 2 与 ASP.NET MVC 4 结合使用来支持可扩展应用程序。这个问题实际上有两个部分(希望诸神没问题):

  1. 我们如何使用 Microsoft.Composition 和 MVC 容器代码 ( MEF/MVC demo source ) 来替换 Ninject 作为 ICoreService 的 DI , ICoreRepository , IUnitOfWork ,和IDbContext
    看起来我们不能同时使用 Ninject 和 MVC 容器(我确信很多人都在说“废话”),所以如果可能的话,我们想使用 MEF。我尝试删除 Ninject 并设置 [Export]每个相关实现的属性,除了 Web 项目之外还跨越两个程序集,但是 Save()未能坚持下去,没有错误。我将其解释为单例问题,但无法弄清楚如何解决它(包括 [Shared] )。

  2. 我们如何在运行时动态加载多个程序集?
    我了解如何使用 CompositionContainer.AddAssemblies()要加载特定的 DLL,但为了使我们的应用程序能够正确扩展,我们需要一些更类似于我(模糊地)理解“完整”MEF 中目录的方式,这些目录已从 Microsoft.Composition 包中删除(我认为?);允许我们加载所有 IPluggable (或其他)程序集,其中将包括自己的 UI、服务和存储库层,并且也与核心服务/存储库相关联。

编辑1
一点more reading解决了第一个问题,这确实是一个单例问题。正在附加[Shared(Boundaries.HttpRequest)] CoreDbContext解决了持久化问题。当我简单地尝试[Shared]时,它将“单例化”扩展到应用程序级别(交叉请求)并抛出异常,表示编辑的对象已经在 EF 缓存中。

编辑2
我使用迭代程序集从下面 Nick Blumhardt 的答案中加载“肉”来更新我的 Global.asax.cs 代码。他的代码中的标准 MEF 2 容器在我的代码中不起作用,可能是因为我使用的是 MEF 2(?) MVC 容器。摘要:下面列出的代码现在可以按预期工作。

<小时/>

CoreDbContext.cs(Data.csproj)

[Export(typeof(IDbContext))]
[Shared(Boundaries.HttpRequest)]
public class CoreDbContext : IDbContext { ... }

CoreRepository.cs(Data.csproj)

[Export(typeof(IUnitOfWork))]
[Export(typeof(ICoreRepository))]
public class CoreRepository : ICoreRepository, IUnitOfWork
{
    [ImportingConstructor]
    public CoreRepository(IInsightDbContext context)
    {
        _context = context;
    }

    ... 
}

CoreService.cs(Services.csproj)

[Export(typeof(ICoreService))]
public class CoreService : ICoreService
{
    [ImportingConstructor]
    public CoreService(ICoreRepository repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitOfWork = unitOfWork;
    }

    ... 
}

UserController.cs (Web.csproj)

public class UsersController : Controller
{
    [ImportingConstructor]
    public UsersController(ICoreService service)
    {
        _service = service;
    }

    ... 
}

Global.asax.cs (Web.csproj)

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        CompositionProvider.AddAssemblies(
            typeof(ICoreRepository).Assembly,
            typeof(ICoreService).Assembly,
        );

        // EDIT 2 -- 
        // updated code to answer my 2nd question based on Nick Blumhardt's answer
        foreach (var file in System.IO.Directory.GetFiles(Server.MapPath("Plugins"), "*.dll"))
        {
            try
            {
                var name = System.Reflection.AssemblyName.GetAssemblyName(file);
                var assembly = System.Reflection.Assembly.Load(name);
                CompositionProvider.AddAssembly(assembly);
            }
            catch
            {
                // You'll need to craft exception handling to
                // your specific scenario.
            }
        }
    }
}

最佳答案

如果我理解正确的话,您正在寻找将从目录加载所有程序集并将它们加载到容器中的代码;这是执行此操作的框架:

var config = new ContainerConfiguration();
foreach (var file in Directory.GetFiles(@".\Plugins", "*.dll"))
{
   try
   {
       var name = AssemblyName.GetAssemblyName(file);
       var assembly = Assembly.Load(name);
       config.WithAssembly(assembly);
   }
   catch
   {
       // You'll need to craft exception handling to
       // your specific scenario.
   }
}
var container = config.CreateContainer();
// ...

Hammett 讨论了这种情况,并在此处展示了 F# 中更完整的版本:http://hammett.castleproject.org/index.php/2011/12/a-decent-directorycatalog-implementation/

请注意,这不会检测应用程序启动后添加到目录中的程序集 - Microsoft.Composition 不适用于此类用途,因此,如果插件集发生更改,您最好的选择是使用以下命令进行检测:目录观察程序并提示用户重新启动应用程序。呵呵!

关于asp.net-mvc - 我们如何使用 ASP.NET MVC 4 和 MEF 2 支持模块化和可测试模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11835473/

相关文章:

c# - MEF 阻止类被手动实例化

javascript - jquery中基于razor循环的循环

javascript - 加载 Spinner - 即使在滚动页面时也始终保持在屏幕中间

c# - 我应该使用 @html.renderpartial 还是 @html.renderaction

c# - Visual Studios 使用 ASP 项目启动错误的 URL?

.net - 使用 MEF 按命名空间解析导入

wpf - PRISM + MEF + MVVM——不确定从哪里开始?

asp.net-mvc - 是否可以在ASP .NET MVC中使用不带 Controller 功能名称的URL?

c# - @Html.RadioButtonFor bool 值

c# - WebActivator.PreApplicationStartMethod 不起作用