第一个问题与MEF引导程序相关:我如何自定义它以让它知道插件文件夹?我知道它的SelectAssemblies重写,但它需要装配件,而我的典型方法将是MEF目录目录。我不想为在目录中找到的每个DLL使用像Assembly.LoadFrom这样的方法:MEF就是为此目的而存在的(生命周期管理等)。那么,我如何做类似于在引导程序中构建DirectoryCatalog的MEF AggregateCatalog呢?
第二个问题: 一旦我拥有所需的VM列表,我想要实例化它们。其中一些需要注入CM服务,例如 IEventAggregator 或 IWindowManager,因此它们具有相应的导入构造函数,因此我需要CM来为我实例化它们:但我需要以编程方式执行此操作,因此我不能只是在属性或导入构造函数上使用Import属性。
对于视图也是如此:一旦我获得了我的VM,我需要CM创建它们并将相应的VM设置为它们的数据上下文;但是我不能使用窗口管理器,因为我只想获取它们,然后以编程方式将它们(它们是用户控件)添加到选项卡控件中,该控件根据数据配置以不同的方式组合。
我使用MEF,因为应用程序是基于插件的,因此当作为IoC使用时,我可以坚持其限制。但是我想利用CM来实例化我的视图和视图模型(全部包含在几个插件DLL中)并正确绑定它们。是否有人可以给出一些提示或指向有关此事的示例或文档?
第二次更新,如承诺的 :):
我基本上按照以下步骤进行:
根据某些应用逻辑实例化所需的VM(使用MEF)。所有VM都是MEF导出项,托管在插件文件夹中的多个插件中。
对于每个VM,调用:
static private object LocateViewFor(object viewmodel) { UIElement view = ViewLocator.LocateForModel(viewmodel, null, null); ViewModelBinder.Bind(viewmodel, view, null); return view; }
这应该通过CM实例化我的视图,这也将满足它们的导入并将每个视图绑定到其VM。使用“标准”的MefBootstrapper(修改为WPF),例如这里。无论如何,这不起作用并返回null。
我必须告诉引导程序在哪里可以找到我的MEF导出。它们在插件文件夹中,如果我不使用CM,我将使用MEF DirectoryCatalog来检查其内容。在CM中,引导程序的典型扩展点是SelectAssemblies重写,这要求我返回一个Assembly对象列表。从文件夹加载所有程序集不是一个选项。根据上述引用页面的建议,我可以像下面这样添加一个方法到我的引导程序中:private IEnumerable GetDirectoryCatalogs() { return new ComposablePartCatalog[] { new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory) // TODO other plugins folders... }; }并修改其配置代码如下:
_container = new CompositionContainer( new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType() .Union(GetDirectoryCatalogs())));这似乎有效地加载了所需的MEF程序集,但这不足以将它们“注册”到CM AssemblySource.Instance中:事实上,我可以通过MEF检索VM,但当我要求CM获取相应的视图时(使用上述方法或调用IWindowManager.ShowDialog(myviewmodel, null)),该方法返回null,或者(对于第二个示例)返回“占位符”文本框,表示找不到VM的视图。
这似乎与视图(如视图模型一样)托管在不同的MEF插件程序集中有关。我确保视图和视图模型共享相同的命名空间并遵循类型SomeNamespace.SampleViewModel - SomeNamespace.SampleView的命名约定;此外,视图和视图模型都通过装饰它们使用[Export]导出,并从公共接口派生。尽管如此,在处理外部程序集时,我无法让CM按预期工作。MEF正常工作,具有所有的导入和导出,但只要CM进入方程式,它就无法执行其“魔法”,从VM中定位视图。
有任何提示吗?