1

我正在尝试了解 MEF 并对此做了一些示例。但是,当我尝试在下面执行这个特定代码时,我遇到了一个例外。

ConsoleApplication2.程序

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;

namespace ConsoleApplication2
{
    class Program 
    {
     [Import(typeof(Contracts.IInput))]
     public Contracts.IInput myinterface { get; set; }

    public void Method()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.ComposeParts(container );
        Console.WriteLine(myinterface.IsValid());
    }

    public static void Main(string[] args)
    {
        var obj = new Program();
        obj.Method();
        Console.ReadLine();
    }

   }
}

我有一个用于定义接口的单独项目。

namespace Contracts
{
   public interface IInput
    {
      //All classes that inherit IInput must implement the IsValid Property.
      string IsValid();
    }
}

在另一个单独的项目中,我使用了一个导出类。

 using System.ComponentModel.Composition;
 using Contracts;

 namespace Plugin
 {
    [Export(typeof(Contracts.IInput))]
    public class Plugin : IInput
    {
        public string IsValid()
        {
             return "1";
        }
    }
 }

现在,所有这些都在同一个“bin\Debug”文件夹中生成(两个库文件和一个可执行文件)。但是在到达代码时执行,“composeParts(this)”会发生如下异常,

Object reference not set to an instance of an object.

当我尝试更改“Composeparts(container)”时,还有另一个异常,如下所示,

**> 合成产生了单个合成错误。根本原因是

下面提供。查看 CompositionException.Errors 属性以获取更多详细信息。

1) 无法填充集合“ConsoleApplication2.Program.myinterface”,因为它没有实现 ICollection 或者是只读的。如果集合不是 IEnumerable 或 T[] 它必须实现 ICollection 并且可以预先初始化或使用默认构造函数可写。

导致:无法激活部分“ConsoleApplication2.Program”元素:ConsoleApplication2.Program --> ConsoleApplication2.Program **

  1. 你能告诉我哪里出错了吗?
  2. 我认为 composeparts(this) 和 composeparts(container) 都是相同的,因为我使用了 Assembly.GetExecutingAssembly()。如果是这样,那么为什么会抛出两个不同的异常?

我用过 importmany 之类的

class Program 
 {
    [ImportMany(typeof(Contracts.IInput))]
    public IEnumerable<Contracts.IInput> myinterface { get; set; }

    public void Method()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);

        try
        {
            container.ComposeParts(container);
            foreach (var i in myinterface)
                Console.WriteLine(i.IsValid());
        }
        catch (CompositionException compositionException)
        {

            Console.WriteLine(compositionException.ToString());
        }



    }

但在这种情况下,myinterface 仍然为 null,这会引发 null 引用异常。

4

1 回答 1

2

有2个问题:

第一:Import不使用ImportMany

或者 由于ImportMany需要一个集合,所以你应该使用这样的东西:

public IEnumerable<Contracts.IInput> myinterface { get; set; }

第二:

正如您不能Import在构造函数中使用具有属性的属性(这就是导入构造函数的用途),您也不能在程序的 Main 函数中访问它们。

例如,这将起作用:

var catalog = new AggregateCatalog();
//Add all the parts found in all assemblies in
//the same directory as the executing program

catalog.Catalogs.Add(
                new DirectoryCatalog(
                    Path.GetDirectoryName(
                    Assembly.GetExecutingAssembly().Location
                    )
                )
            );

var container = new CompositionContainer(catalog);
container.ComposeParts(container);

// Use the container to get a value for myinterface
myinterface = container.GetExportedValue<Contracts.IInput>();
Console.WriteLine(myinterface.IsValid());
于 2012-11-05T08:48:30.050 回答