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 的了解也很有限。
抱歉,如果描述令人困惑,我会尽力解决任何其他问题。
版本
- .NET 4.5.2
- Unity 3.5(也尝试引用克隆的 Unity 存储库作为基准版本)
- MEF 直接来自 .NET 4.5.2(不是 MEF 2)
为什么要同时使用这两个框架?
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);
在 Prism 应用程序中,您想在 Bootstrapper
中执行此操作作为 CreateContainer
覆盖的一部分。或者 MEF 将无法解析 Prism 提供给 Unity 的很多东西,例如 IUnityContainer
、IEventAggregator
或 IRegionManager
.
我正在尝试在我使用 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 的了解也很有限。
抱歉,如果描述令人困惑,我会尽力解决任何其他问题。
版本
- .NET 4.5.2
- Unity 3.5(也尝试引用克隆的 Unity 存储库作为基准版本)
- MEF 直接来自 .NET 4.5.2(不是 MEF 2)
为什么要同时使用这两个框架? 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);
在 Prism 应用程序中,您想在 Bootstrapper
中执行此操作作为 CreateContainer
覆盖的一部分。或者 MEF 将无法解析 Prism 提供给 Unity 的很多东西,例如 IUnityContainer
、IEventAggregator
或 IRegionManager
.