"缺少依赖性" MEF 2例外

时间:2014-09-04 07:50:49

标签: .net mef

我正在研究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,有2个版本的MEF。

  • 使用.NET Framework支持的非便携式文件
  • 便携式可在NuGet
  • 上找到

List<IMessageSender>方法适用于非便携式方法。但不是便携式的。这是一个错误吗?

2 个答案:

答案 0 :(得分:3)

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

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

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

它解决了这个问题。

但是,为什么呢?不是List<T> IEnumerable<T>吗?

ADD

甚至更奇怪,我将IEnumerable更改为IList,它的工作原理。为什么呢?

可能的解释

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

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

interface IMyList<T> : IList<T>
{

}

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

以下MEF 2来源显示原因。

enter image description here

3 SupportedContactTypes的Equals()方法返回false,其中包含IMyList&lt;&gt;。所以在MEF2中不会返回IMyList&lt;&gt;的有效导出。 并且MEF 2不允许使用[ImportMany]属性修饰的属性的默认值。因此,在以下逻辑中,将抛出依赖性缺失异常。

enter image description here

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

答案 1 :(得分:0)

评论时间有点太长了:

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

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