【问题标题】:"Missing dependency" exception with MEF 2MEF 2 的“缺少依赖项”异常
【发布时间】:2014-09-04 07:50:48
【问题描述】:

我正在学习 MEF 2。下面的代码抛出异常:

未处理的类型异常 'System.Composition.Hosting.CompositionFailedException' 发生在 System.Composition.TypedParts.dll

附加信息:缺少依赖项“MessageSenders” 'MEFStudy.Program'。

调用 SatisfyImports() 方法时。为什么?

using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;


using System.Reflection;

namespace MEFStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }

        [ImportMany]
        private List<IMessageSender> MessageSenders { get; set; }

        public void Run()
        {
            Compose();
            foreach (IMessageSender sender in MessageSenders)
            {
                sender.Send();
            }

        }

        private void Compose()
        {
            CompositionHost host = new ContainerConfiguration().WithAssembly(Assembly.GetExecutingAssembly()).CreateContainer();
            host.SatisfyImports(this);   // <=========== HERE
            host.Dispose();

        }
    }

    public interface IMessageSender
    {
        void Send();
    }

    [Export(typeof(IMessageSender))]
    public class EmailSender1 : IMessageSender
    {
        public void Send()
        {
            Console.WriteLine("EmailSender1");
        }
    }

    [Export(typeof(IMessageSender))]
    public class EmailSender2 : IMessageSender
    {
        public void Send()
        {
            Console.WriteLine("EmailSender2");
        }
    }

}

更新 1

根据here,MEF有2个版本。

  • .NET Framework 随附的非便携式计算机
  • 可在 NuGet 上使用的便携式计算机

List&lt;IMessageSender&gt; 方法适用于非便携式方法。但不是便携式的。这是一个错误吗?

【问题讨论】:

    标签: .net mef


    【解决方案1】:

    我不小心更改了以下代码:

    [ImportMany]
    private List<IMessageSender> MessageSenders { get; set; }
    

    [ImportMany]
    private IEnumerable<IMessageSender> MessageSenders { get; set; }
    

    它解决了问题。

    但是,为什么? List&lt;T&gt; 不是 IEnumerable&lt;T&gt; 吗?

    添加

    更奇怪的是,我将 IEnumerable 更改为 IList,它可以工作。为什么?

    可能的解释

    (我想分享我对此的解释。)

    以下界面可以重现完全相同的错误。

    interface IMyList<T> : IList<T>
    {
    
    }
    
    [System.Composition.ImportMany] // MEF 2
    private IMyList<IMessageSender> MessageSenders { get; set; }
    

    下面的 MEF 2 源码说明了原因。

    3 SupportedContactTypes 的 Equals() 方法使用 IMyList 返回 false。所以在 MEF2 中不会返回 IMyList 的有效导出。 并且 MEF 2 不允许使用 [ImportMany] 属性装饰的属性没有默认值。所以在下面的逻辑中,会抛出依赖缺失异常。

    所以我们可以说,ImportMany 属性只支持数组和支持的 3 种泛型类型。

    【讨论】:

    • 虽然我可能已经找到了根本原因。我不知道这背后的理性。我会为此开始赏金。
    【解决方案2】:

    评论有点太长了:

    我的猜测是 MEF 旨在用于接口,而不是具体类。因此,对我来说,缺少对 List 的依赖似乎是一种设计选择,MEF 只是缺少它的导出定义。

    在您期望 IMyList 的情况下,同样的机制适用:MEF 没有与要实例化的接口关联的具体类型,因为没有为它定义导出。即使 List 满足所有要求,也需要为 IMyList 显式导出它。 (例如,这对于单元测试很方便,因为您只需要将导出更改为您的 Mock 对象。)

    【讨论】:

      猜你喜欢
      • 2015-04-08
      • 2017-07-10
      • 2017-12-25
      • 2015-04-18
      • 2020-03-24
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多