>我们如何使用Microsoft.Composition和MVC容器代码(MEF/MVC demo source)将Ninject替换为ICoreService,ICoreRepository,IUnitOfWork和IDbContext的DI?
看起来我们不能同时使用Ninject和MVC容器(我确信很多人都在说“duh”),所以如果可能的话,我们想和MEF一起使用.我尝试删除Ninject并在每个相关实现上设置[Export]属性,除了Web项目之外还包含两个程序集,但Save()无法保持没有错误.我将其解释为单例问题,但无法弄清楚如何对其进行排序(包括[共享]).
>我们如何在运行时动态加载多个程序集?
我理解如何使用CompositionContainer.AddAssemblies()来加载特定的DLL,但是为了使我们的应用程序能够正确扩展,我们需要更类似于我(模糊地)理解“完整”MEF中的目录的内容,这些内容已被从中删除Microsoft.Composition包(我想?);允许我们加载所有IPluggable(或其他)程序集,这些程序集将包括它们自己的UI,服务和存储库层,并且也可以绑定到Core服务/存储库.
编辑1
一点点more reading解决了第一个问题,这个问题确实是一个单例问题.将[Shared(Boundaries.HttpRequest)]附加到CoreDbContext解决了持久性问题.当我尝试简单地[共享]时,它将“单例化”扩展到应用程序级别(交叉请求)并抛出一个异常,说明编辑的对象已经在EF缓存中.
编辑2
我使用了来自Nick Blumhardt的答案的迭代程序集“meat”来更新我的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不适合这种用途,因此如果插件集更改,最好的办法是使用目录监视器检测到并提示用户重新启动应用程序. HTH!