【问题标题】:ImportMany with Metadata not importing元数据未导入的 ImportMany
【发布时间】:2010-09-02 08:07:08
【问题描述】:

我这几天一直在尝试解决这个问题,但没有成功。

我正在尝试使用 [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 永远不会被填充。我没有收到任何合成错误。

我认为这可能与懒惰有关,所以我尝试了

public ObservableCollection<IEditorSystem> EditorSystemList

也没有运气。

我能想到的唯一复杂情况是我正在使用 Cinch,它使用 MEFedMVVM,它也使用 MEF。我不认为它会干扰,但我不太确定。

我觉得我做错了,有人能理解吗?

更新:

实现一个新的 IComposer,其中包含您需要的目录。

ImportMany 仍然失败,但只有当我尝试使用它导入元数据时。元数据只是几个字符串,据我所知,遵循示例。

终于找到了原因:如前所述,IEditorSystem 的实现位于单独的 DLL 中。 但是,dll 的任何新版本都不会复制到主项目的输出子目录。 我手动复制了第一个,忘记将构建后的副本添加到 dll 项目中。 哦,好吧,学到了很多关于 MEF 的东西,所以没有完全浪费时间 :)

【问题讨论】:

    标签: mef


    【解决方案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; }
    }
    

    【讨论】:

    • 我将其更改为 IEnumerable,但导入似乎永远无法完成,EditorSystemList 仍为 [0]...
    • 您是否尝试从上面运行确切的代码?您应该能够创建一个控制台应用程序来测试它。
    • 是的,控制台版本可以工作,但看起来可能是由于 MEFedMVVM 搞砸了,会更新
    【解决方案2】:

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

    我一直在努力发现问题。

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

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

    int、bool、string等。如果你放两个Int的属性,比如ImportMany>不起作用,它总是返回0。

    对于接口的每个属性,都必须把ExportMetadata Attribute放在导出的类到。

    例如,

    公共接口IMyExportMetadata { 诠释一个{get;} 字符串 b {get; } 布尔 c {得到;} }

    [导出(typeof(IMyInterface)) [导出元数据(“a”,0)] [导出元数据(“b”,“字符串”)] [导出元数据(“c”,真)] 公共类 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;
        }
         */
    }
    

    【讨论】:

      【解决方案3】:

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

      我一直在努力发现问题。

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

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

      intboolstring等。如果你放了int的两个属性,比如ImportMany&lt;Lazy&lt;t,m&gt;&gt;就不起作用,它总是返回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
      {
      }
      

      【讨论】:

        猜你喜欢
        • 2013-12-28
        • 1970-01-01
        • 2021-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-13
        • 2019-11-12
        • 1970-01-01
        相关资源
        最近更新 更多