ImportMany元数据不导入

时间:2010-09-02 08:07:09

标签: mef

我一直试图想这几天,没有运气。

我正在尝试使用[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的东西,所以不是完全浪费了几天:)

3 个答案:

答案 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)

也许我的解决方案也解决了你的问题。

我正努力尝试发现问题。

然后我得到了以下解决方案:

元数据接口应该只包含一个相同类型的属性:

intboolstring等。例如,如果您放置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
{
}