Unity与MEF合作

Unity and MEF cooperation

我正在尝试在我使用 Unity 处理 DI 的应用程序中实现基本模块加载系统。我认为使用 FileSystemWatcher 和 MEF 添加动态加载会很容易,但我 运行 遇到了问题。

简介

在用模块注册目录时,我读取目录中当前存在的模块并设置 FileSystemWatcher

public List<IModule> RegisterModule(string directoryUri){
        var fsw = new FileSystemWatcher(directoryUri, "*.dll");
        fsw.Created += OnModulesChange;
        fsw.EnableRaisingEvents = true;

        return GetModules();
}

在处理程序中,我刷新 MEF 目录目录并触发通知容器已更改的事件

private void OnModulesChange(object sender, FileSystemEventArgs e)
{
   _catalog.Catalogs.OfType<DirectoryCatalog>().ForEach(x => x.Refresh());
   ModuleDirectoryChanged?.Invoke(this);
   lastRead = DateTime.Now;
}

每个订阅者都通过 GetModules 方法再次读取新模块:

public List<IModule> GetModules()
{
   var directories = _mefContainer.GetExports<IModule>().Select(x => x.Value).ToList();
   directories.ForEach(x => x.RegisterModule(this));
   return directories.Concat(_staticModules).ToList();
}

在 RegisterModule 方法中,我用 Unity 做了一些解析。现在有很多逻辑,但最后我使用的唯一相关方法是:

public T Resolve<T>() where T : class, IMyThing
{            
   return this._container.Resolve<T>();
}

问题

当第一次调用 GetModules 时,一切正常(当 运行 应用程序并在启动时注册目录时,我只是在目录中有带模块的 dll)。我可以在 Resolve 方法上放置断点,然后看到所有内容都已注册并且对象已真正解析。

但是当我将另一个 .dll 复制到该目录时,我从 Resolve 方法中得到 ResolutionFailedException。如果我查看容器,我会像以前一样看到 Registrations 类型。使用相同的容器,调用相同的方法,唯一不同的是调用是由 FileSystemWatcher 发起的。

我做错了什么?这可能是一个系统问题,因为我从未将 MEF 和 Unity 一起使用,而且我对 Unity 的了解也很有限。

抱歉,如果描述令人困惑,我会尽力解决任何其他问题。

版本

为什么要同时使用这两个框架? Unity 和 MEF 都是依赖注入管理器 这些框架的实现方式不同,因此各有优缺点。

希望以下链接对您有所帮助:

这些库可以一起使用,如果您需要 DI 和可扩展性,您可能会想要。

问题是 Unity 容器和 MEF catalog/container 彼此不了解。在 NuGet 上安装 MefContrib.Integration.Unity,您可以使用以下代码使它们协同工作:

// Setup
var unityContainer = new UnityContainer();
var aggregateCatalog = new AggregateCatalog();

// Register catalog
unityContainer.RegisterCatalog(aggregateCatalog);

Read More...

在 Prism 应用程序中,您想在 Bootstrapper 中执行此操作作为 CreateContainer 覆盖的一部分。或者 MEF 将无法解析 Prism 提供给 Unity 的很多东西,例如 IUnityContainerIEventAggregatorIRegionManager.