我们正在尝试使用 MEF 2 和 ASP.NET MVC 4 来支持可扩展的应用程序。这个问题实际上有两个部分(希望没关系,所以上帝):
我们如何使用 Microsoft.Composition 和 MVC 容器代码(MEF/MVC 演示源)来替换 Ninject 作为我们的 DIICoreService
、ICoreRepository
、IUnitOfWork
和IDbContext
?
看起来我们不能同时使用 Ninject 和 MVC 容器(我相信很多人都在说“duh”),所以如果可能的话,我们想使用 MEF。我尝试删除 Ninject 并[Export]
在每个相关实现上设置属性,除了 Web 项目之外还跨越两个程序集,但Save()
未能坚持没有错误。我将其解释为单例问题,但不知道如何解决(包括[Shared]
)。我们如何在运行时动态加载多个程序集?
我了解如何使用CompositionContainer.AddAssemblies()
来加载特定的 DLL,但是为了使我们的应用程序能够正确扩展,我们需要更类似于我(模糊地)理解“完整”MEF 中的目录的方式,这些目录已从 Microsoft.Composition 包中删除(我认为?); 允许我们加载所有IPluggable
(或其他)程序集,这些程序集将包括它们自己的 UI、服务和存储库层,并与核心服务/存储库相关联。
编辑 1多读
一点解决了第一个问题,这确实是一个单例问题。附加到 CoreDbContext 解决了持久性问题。当我简单地尝试时,它将“单例化”扩展到应用程序级别(交叉请求)并抛出异常,指出编辑的对象已经在 EF 缓存中。[Shared(Boundaries.HttpRequest)]
[Shared]
编辑 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;
}
...
}
用户控制器.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.
}
}
}
}