mef - Caliburn Micro:基于MEF的方案的插件相关问题

标签 mef caliburn.micro

我有一个使用WPF应用程序的场景,该应用程序托管一些带有其视图模型的视图(用户控件),这些视图模型是MEF在其插件文件夹中导出的部件。该应用程序将其数据与配置文件一起加载,该文件还指示应在可用零件中导入哪些零件。

第一个问题与MEF引导程序有关:如何自定义它以使其了解plugins文件夹?我知道它的SelectAssemblies重写,但是它需要程序集,而我的典型方法是使用MEF目录目录。我不想为目录中找到的每个DLL使用Assembly.LoadFrom之类的方法:MEF就是用于此目的(生命周期管理等)。那么,我该如何做与引导程序中由DirectoryCatalog构建的MEF AggregateCatalog类似?

第二个问题:一旦有了所需的VM列表,我想实例化它们。其中一些需要注入IEventAggregator或IWindowManager之类的CM服务,以便它们具有相应的导入构造函数,因此我需要CM为我实例化它们:但是我需要以编程方式进行此操作,因此我不能仅使用Import属性或导入构造函数上的属性。

对于视图也是如此:一旦获得虚拟机,就需要CM创建它们并将相应的虚拟机设置为其数据上下文。但是我不能使用窗口管理器,因为我只想获取它们,然后以编程方式将它们(它们是用户控件)添加到选项卡控件中,该控件根据数据配置的不同而不同。

我之所以使用MEF,是因为该应用程序是以插件为中心的,因此在用作IoC时我可以坚持其限制。但是我想利用CM实例化我的视图和视图模型(都包含在多个插件DLL中)并正确绑定它们。有人可以提供一些提示或指向有关此的示例或文档吗?

如承诺的第二次更新:):

我基本上遵循以下步骤:


根据某些应用程序逻辑实例化(使用MEF)所需的VM。所有虚拟机都是MEF导出,托管在plugins文件夹中的多个插件中。
对于每个虚拟机,调用:


静态私有对象LocateViewFor(object viewmodel)
{
UIElement view = ViewLocator.LocateForModel(viewmodel,null,null);
ViewModelBinder.Bind(viewmodel,view,null);
返回视图
}


这应该通过CM来确保我的视图,这也将满足其导入并将每个视图绑定到其VM的需求。使用为WPF修改的“标准” MefBootstrapper(请参见例如here)。无论如何,这不起作用并返回null。

我必须告诉引导程序在哪里可以找到我的MEF出口。它们位于plugins文件夹中,如果我不使用CM,则可以使用MEF DirectoryCatalog来检查其内容。 CM中引导程序的典型扩展点是SelectAssemblies覆盖,这需要我返回Assembly对象的列表。无法从文件夹加载所有部件。按照上面引用的页面中的建议,我可以做一些类似的事情,在我的引导程序中添加这样的方法:

私有IEnumerable GetDirectoryCatalogs()
{
返回新的ComposablePartCatalog []
{
新的DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory)
// TODO其他插件文件夹...
};
}


并修改其配置代码,例如:

_container =新的CompositionContainer(
新的AggregateCatalog(AssemblySource.Instance.Select(x =>新的AssemblyCatalog(x))。OfType()
.Union(GetDirectoryCatalogs())));


这似乎有效地加载了与MEF一样的必需程序集,但不足以将它们“注册”到CM AssemblySource.Instance:实际上,我可以通过MEF检索VM,但是当我要求CM获取相应视图时(使用上面的方法,或者调用IWindowManager.ShowDialog(myviewmodel,null),我从该方法中获得null,或者(对于第二个示例)“占位符”文本框表示找不到我的VM的视图。

这似乎与以下事实有关:视图(如viewmodel)托管在另一个程序集中,即我的MEF插件。我确保视图和视图模型共享相同的名称空间,并遵循SomeNamespace.SampleViewModel类型的命名约定-SomeNamespace.SampleView;。同样,视图和视图模型都通过用[Export]装饰来导出,并从通用接口派生。但是,在处理外部程序集时,我无法使CM正常工作。 MEF可以正常使用所有进出口,但是,一旦CM输入方程式,便无法执行其“魔术”功能,也无法从VM定位视图。

有什么提示吗?

最佳答案

我以前从未对Caliburn Micro做任何事情,但是它使用CompositionInitializer组件来满足进口要求吗?如果是这样,您可以使用CompositionHost手动初始化用于满足进口要求的容器,例如:

var catalog = new AggregateCatalog(
    new DirectoryCatalog("bin"),
    new DirectoryCatalog("Plugins"));

CompositionHost.Initialise(catalog);


CompositionInitialiser.SatisfyImports(...)的任何调用都将使用根据您创建的目录构造的容器。

如果希望能够以编程方式创建导出实例,则需要引用实际的CompositionContainer本身。但是,为此,我们需要另一种初始化构图的替代方法。您可以创建一个容器并保存对其的引用,例如:

var catalog = new AggregateCatalog(
    new DirectoryCatalog("bin"),
    new DirectoryCatalog("Plugins"));
var container = new CompositionContainer(catalog);
CompositionHost.Initialise(container);

Container = container;


...其中Container是对CompositionContainer实例的静态引用。我们已将对CompositionHost的调用更改为特定于CompositionInitializer将使用的确切容器,以便所有容器仍能正常工作,但是我们有了一个可用于创建特定实例的容器,例如:

var viewModel = Container.GetExport<ISomeViewModel>();


有帮助吗?

关于mef - Caliburn Micro:基于MEF的方案的插件相关问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6230601/

相关文章:

mef - 线程安全和 MEF CompositionContainer

mef - MEF Container.Dispose 是否处理添加的目录?

mef - CompositionBatch 和目录之间有什么区别?

wpf - MVVM应用程序无法正确还原状态

c# - MEF 加载和卸载特定插件?

c# - 在 Windows 8 应用程序中使用 MessageBinder.SpecialValues 不起作用?

menuitem - Caliburn.Micro 子菜单项如何单击在包含 View 的 View 模型上调用操作?

viewmodel - Caliburn.Micro ViewModel 和 ActivateItem - 在当前上下文中不存在

c# - 在 XAML 中绑定(bind) Itemscontrol 之外的属性

silverlight - Caliburn Entity DataBinding 有趣