几天来我一直在尝试解决这个问题,但没有运气。
我正在尝试使用 [ImportMany] 从充满 DLL 的目录中导入,该目录具有 IEditorSystem 类型的导出,并且具有 IEditorSystemMetadata 类型的自定义元数据。我想首先获取元数据,然后将其推送到一些文本框等,以便用户可以选择要使用的 EditorSystem,并在选择后加载该系统...
我一直在尽我所能地遵循示例,这是我到目前为止所拥有的。
[ImportMany]
public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList
这就是它应该导入的内容:
[Export(typeof(IEditorSystem))]
[SignalSystemData("Very Very Long Name", "Short Name")]
public class MyEditorSystem: IEditorSystem
{
public MyEditorSystem()
{
}
}
以及启动:
AggregateCatalog Catalog = new AggregateCatalog(
new DirectoryCatalog(@".\EditorSystems"),
new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer Container = new CompositionContainer(Catalog);
Container.ComposeParts(this);
我可以在 Catalog.Parts 中看到 MyEditorSystem 和具有 ImportMany 的视图模型,但 EditorSystemList 永远不会被填充。我没有收到构图错误。
我认为这可能与Lazy<>有关,所以我尝试了
public ObservableCollection<IEditorSystem> EditorSystemList
也没有运气。
我能想到的唯一复杂之处是我使用的是 Cinch,它使用 MEFedMVVM,它也使用 MEF。我不认为它会干扰,但我不太确定。
我想我做错了,有人能理解吗?
更新:
实现一个新的 IComposer,其中包含您需要的目录。
不过,ImportMany 仍然失败,但只有当我尝试用它导入元数据时才会失败。元数据只是几个字符串,据我所知,遵循示例。
终于找到了原因:IEditorSystem 的实现位于单独的 DLL 中,如前所述。
但是,任何新构建的 dll 都不会复制到主项目的输出子目录中。
我手动复制了第一个,但忘记将构建后副本添加到 dll 项目中。
哦,好吧,学到了很多关于 MEF 的东西,所以没有完全浪费时间:)
I've been trying to figure this for a few days now, with no luck.
I'm trying to use the [ImportMany] to import from a directory full of DLL's with exports of type IEditorSystem, that have custom metadate of type IEditorSystemMetadata. I'd like to get the metadata first, and push it out to some textboxs etc so the user can choose which EditorSystem to use, and when selected, load that system...
I've been following examples as best as I can, here's what I have so far.
[ImportMany]
public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList
This is what it should be importing:
[Export(typeof(IEditorSystem))]
[SignalSystemData("Very Very Long Name", "Short Name")]
public class MyEditorSystem: IEditorSystem
{
public MyEditorSystem()
{
}
}
and the startup:
AggregateCatalog Catalog = new AggregateCatalog(
new DirectoryCatalog(@".\EditorSystems"),
new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer Container = new CompositionContainer(Catalog);
Container.ComposeParts(this);
I can see in the Catalog.Parts both the MyEditorSystem and the viewmodel that has the ImportMany, but EditorSystemList never gets populated. I get no Composition errors.
I thought it might have something to do with the Lazy<>, so i tried
public ObservableCollection<IEditorSystem> EditorSystemList
No luck either.
The only complication I can think of is that I'm using Cinch, which uses MEFedMVVM, which also uses MEF. I don't think it interferes, but I'm not really sure.
I figure I'm doing it wrong, can anyone make sense of this?
Update:
Implement a new IComposer, with exactly the catalog you need.
ImportMany is still failing though, but only when I try to import metadata with it. The metadata is just a couple of strings, and as far as I am able to determine, follows the examples.
FINALLY found the cause: The implementations of IEditorSystem are in a seperate DLL, as noted before.
However, any new builds of the dll are not copied to the output subdir of the main project.
I had copied the first one manually, and forgot to add a post-build copy to the dll project.
Oh well, learned a bunch of stuff about MEF, so not completely wasted days :)
发布评论
评论(3)
在没有看到您的代码的情况下,我相信您需要更改的只是
下面
是一个示例:
Without seeing your code, I believe all you need to change is
should be
Here is a sample:
也许我的解决方案也能解决您的问题。
我正在努力尝试发现问题。
然后我得到了以下解决方案:
Metadata接口应该只包含一个相同类型的属性:
int,bool,string等。如果你放Int的两个属性,例如,ImportMany>;不起作用,并且始终返回 0。
对于接口的每个属性,您必须将 ExportMetadata 属性放在导出的类中。
例如,
公共接口 IMyExportMetadata
{
int a {获取;}
字符串 b {获取; }
布尔 c {获取;}
}
[导出(类型(IMyInterface))
[导出元数据(“a”,0)]
[导出元数据(“b”,“字符串”)]
[导出元数据(“c”,true)]
公共类 myExportedClass:IMyInterface
{
例如
,要使用多个布尔值,您必须创建一个实现元数据接口的自定义导出属性,如下所示:
Maybe my solution solves your problem too.
I was working hard trying to discover the problem.
then I got the following solution:
Metadata interface should contain only one property of the same type:
int, bool, string, etc. If you put two properties of Int, for example, the ImportMany> will not work and it will always return 0.
for each property of the interface, you must put the ExportMetadata Attribute at the exported class to.
for example,
public interface IMyExportMetadata
{
int a {get;}
string b {get; }
bool c {get;}
}
[Export(typeof(IMyInterface))
[ExportMetadata("a", 0)]
[ExportMetadata("b", "string")]
[ExportMetadata("c", true)]
public class myExportedClass: IMyInterface
{
}
to work with multiple booleans, for example, you must create a custom export attribute implementing the metadata interface like this:
也许我的解决方案也能解决您的问题。
我正在努力尝试发现问题。
然后我得到了以下解决方案:
元数据接口应该只包含一个相同类型的属性:
int
,bool
,string
等。如果你输入两个int
属性,例如,ImportMany>
将不起作用,并且始终返回 0。对于接口的每个属性,您必须将
ExportMetadata
属性放在导出的类中。例如,
Maybe my solution solves your problem too.
I was working hard trying to discover the problem.
then I got the following solution:
Metadata interface should contain only one property of the same type:
int
,bool
,string
, etc. If you put two properties ofint
, for example, theImportMany<Lazy<t,m>>
will not work and it will always return 0.for each property of the interface, you must put the
ExportMetadata
Attribute at the exported class to.for example,