1

私はMEFを理解しようとしていて、その上でいくつかのサンプルを作成しました。しかし、以下のこの特定のコードを実行しようとすると、例外が発生します。

ConsoleApplication2.program

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」フォルダに(2つのライブラリファイルと実行可能ファイル)を生成します。ただし、コード「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. Assembly.GetExecutingAssembly()を使用しているので、composeparts(this)とcomposeparts(container)はどちらも同じだと思いました。もしそうなら、なぜ2つの異なる例外がスローされたのですか?

私は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; }

2番:

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 に答える