我一直试图想这几天,没有运气。
我正在尝试使用[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.Part中看到MyEditorSystem和具有ImportMany的viewmodel,但是从未填充EditorSystemList。我没有收到错误。
我认为它可能与Lazy&lt;&gt;有关,所以我试过
public ObservableCollection<IEditorSystem> EditorSystemList
也没有运气。
我能想到的唯一复杂因素是我正在使用Cinch,它使用MEFedMVVM,它也使用MEF。我不认为它会干扰,但我不确定。
我认为我做错了,有人能理解这个吗?
更新
实施一个新的IComposer,其中包含您需要的目录。
然而,ImportMany仍然失败,但只有当我尝试使用它导入元数据时才会失败。元数据只是几个字符串,据我所知,请遵循示例。
最后找到原因:IEditorSystem的实现是在一个单独的DLL中,如前所述。 但是,dll的任何新版本都不会复制到主项目的输出子目录中。 我手动复制了第一个,忘了将后期构建副本添加到dll项目中。 哦,好好学习了一堆关于MEF的东西,所以不是完全浪费了几天:)
答案 0 :(得分:1)
如果没有看到您的代码,我相信您需要改变的是
public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList
应该是
public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList;
以下是一个示例:
class Program
{
static void Main(string[] args)
{
var c = new Class1();
var v = c.EditorSystemList;
foreach (var lazy in v)
{
if (lazy.Metadata.LongName == "Very Very Long Name")
{
var v2 = lazy.Value;
// v2 is the instance of MyEditorSystem
}
}
}
}
public class Class1
{
[ImportMany]
public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList;
public Class1()
{
var catalog = new AggregateCatalog(
new AssemblyCatalog(Assembly.GetExecutingAssembly()));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
[Export(typeof(IEditorSystem))]
[SignalSystemData("Very Very Long Name", "Short Name")]
public class MyEditorSystem : IEditorSystem { }
public interface IEditorSystem { }
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class SignalSystemDataAttribute : ExportAttribute
{
public SignalSystemDataAttribute(string longName, string shortName)
: base(typeof(IEditorSystem))
{
LongName = longName;
ShortName = shortName;
}
public string LongName { get; set; }
public string ShortName { get; set; }
}
public interface IEditorSystemMetadata
{
string LongName { get; }
string ShortName { get; }
}
答案 1 :(得分:1)
也许我的解决方案也解决了你的问题。
我正努力尝试发现问题。
然后我得到了以下解决方案:
元数据接口应该只包含一个相同类型的属性:
int,bool,string等。如果你输入Int的两个属性,例如,ImportMany&gt;不起作用,它将始终返回0.
对于接口的每个属性,必须将ExportMetadata属性放在导出的类中。
例如,
公共接口IMyExportMetadata { int a {get;} string b {get; } bool c {get;} }
[导出(typeof运算(IMyInterface的)) [ExportMetadata(“a”,0)] [ExportMetadata(“b”,“string”)] [ExportMetadata(“c”,true)] public class myExportedClass:IMyInterface { }
例如,使用多个布尔值,您必须创建一个实现元数据接口的自定义导出属性,如下所示:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ExportUserPartAttribute : ExportAttribute, IUserPartMetadata
{
#region Implementation of IUserPartMetadata
public int TipoPart { get; set; }
public string Regiao { get; set; }
public bool IsLogin { get; set; }
public bool IsMenu { get; set; }
public bool IsHome { get; set; }
public bool IsListagem { get; set; }
public bool IsFormulario { get; set; }
#endregion
public ExportUserPartAttribute()
: base(typeof(IUserPart))
{
}
/*
public ExportUserPartAttribute(int tipoPart, string regiao)
: base(typeof(IUserPart))
{
this.TipoPart = tipoPart;
this.Regiao = regiao;
}
*/
}
答案 2 :(得分:0)
也许我的解决方案也解决了你的问题。
我正努力尝试发现问题。
然后我得到了以下解决方案:
元数据接口应该只包含一个相同类型的属性:
int
,bool
,string
等。例如,如果您放置int
的两个属性,则ImportMany<Lazy<t,m>>
将无效总是返回0。
对于接口的每个属性,必须将ExportMetadata
属性放在导出的类中。
例如,
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
{
}