0

ニーズ -

  1. 同じインターフェースの共有エクスポートを宣言するため。エクスポートは一意のエクスポート名でマークされているため、消費者はエクスポートの特定のフレーバーをインポートできます。
  2. クラスの共通インスタンスをオブジェクトのセットに注入するが、オブジェクトのセット間で共通のインスタンスを共有しない [これにより、異なるキーを使用して共有エクスポートを使用するようになります - オブジェクトの 1 つのセットは、共有インポートを満たすために単一のキーを使用できます。必要]

これがエクスポートクラスです

public interface IMyExport
{
    void Display();
}

public class MyExport : IMyExport
{
    private Guid _id = Guid.NewGuid();

    public void Display()
    {
        Console.WriteLine("Instance ID = "+_id);
    }
}

クラスのインスタンスをエクスポートする方法は次のとおりです

public static class ExportInitialization
{
    [Export("Type A", typeof(IMyExport)),
    Export("Type B", typeof(IMyExport))]
    public static IMyExport IceCreamExport
    {
        get
        {
            return new MyExport();
        }
    }
}

消費者は、次の方法で特定のインスタンスをインポートできます

[Export]
public class ImporterA
{
    private readonly IMyExport _myExport;

    [ImportingConstructor]
    public ImporterA([Import("Type A")]IMyExport myExport)
    {
        _myExport = myExport;
    }

    public void Display()
    {
        _myExport.Display();
    }
}

[Export]
public class ImporterB
{
    private readonly IMyExport _myExport;

    [ImportingConstructor]
    public ImporterB([Import("Type B")]IMyExport myExport)
    {
        _myExport = myExport;
    }

    public void Display()
    {
        _myExport.Display();
    }
}

class Program
{
    [Import]
    public ImporterA ImporterA { get; set; }

    [Import]
    public ImporterB ImporterB { get; set; }

    static void Main(string[] args)
    {
        new Program().Run();
    }

    public void Run()
    {
        var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
        container.ComposeParts(this);

        ImporterA.Display();
        ImporterB.Display();

        Console.ReadKey();
    }
}

これは以前は.Net 4.0で正常に機能していましたが、.Net 4.5がインストールされている場合、次の出力が得られます

Instance ID = 78bba41a-0c48-44fc-ae69-f0ead96371f9
Instance ID = 78bba41a-0c48-44fc-ae69-f0ead96371f9

オブジェクトの同じインスタンスが両方のインポートで返されることに注意してください。静的プロパティを介したエクスポートに関する文書化されていない規則に違反していますか?

4

2 に答える 2

1

2 つの異なる静的プロパティから特定のインスタンスをエクスポートすると、2 つの異なるインスタンスが確実に返されることがわかりました。

    [Export("Type A", typeof(IMyExport))]
    public static IMyExport ExportA
    {
        get
        {
            return new MyExport();
        }
    }

    [Export("Type B", typeof(IMyExport))]
    public static IMyExport ExportB
    {
        get
        {
            return new MyExport();
        }
    }

変更されていないバージョンでは、静的 getter が get ごとに新しいインスタンスを作成していたため、これは不可解です。これが 4.5 で導入された C#/.Net 最適化の結果なのか、それとも MEF の問題なのかは不明です

于 2013-02-25T10:04:53.070 に答える
0

これは、MEF 部品の寿命に関連しています。

MEF 属性のデフォルトでは、コンポーネントは毎回新しいインスタンスを取得する必要があるかどうかを示しません。

つまり:

  • ExportAttributeエクスポートされたインスタンスを共有できるかどうか、または共有する必要があるかどうかを指定しません。
  • どちらの もImportAttribute、インポートを共有するかどうかを指定していません。

MEF の既定の動作では、インスタンスの共有が禁止されていない場合は、共有されます。つまり、ドキュメントによると、.NET 4.5 の動作は正しいものですMyExport。どちらの側でも明示的に共有を禁止していないことを考えると、のインスタンスは共有されます。

.NET 4.0 には、静的プロパティが毎回呼び出されるバグ/不一致があり、その結果、観察されたもの、つまり非共有インスタンスが発生したと思います。そして、あなたはそのバグに依存していました。このバグは、プロパティに対するフレームワーク全体の基本的な期待にその起源があると思います。プロパティ呼び出しごとに、静的プロパティが新しい、意味的に異なるインスタンスを作成することは非常にまれです。

私はあなたがすべきだと信じています:

  1. 静的プロパティのエクスポートを静的メソッドのエクスポートに置き換えます。
  2. エクスポート側またはインポート側のいずれかで、作成ポリシーを非共有に指定します。
于 2013-02-25T09:50:43.307 に答える