2012-03-18 1 views
5

は、ここで私はそれは違いはコンテナはそれが含まれていない場合、このメソッドは、インスタンスを作成しないということです既存のエクスポートされた値/オブジェクトを取得するMEFメソッドとは何ですか(取得または作成できません)。

container.GetButDoNotCreate<T>(); // should throw (or can return null) if container doesn't contain an instance matching the contract 

var x = container.GetExportedValue<T>(); 

var y = container.GetButDoNotCreate<T>(); // should return the object created in previous step 

Assert.That(x).IsSameAs(y); 

働きたい方法です。これは純粋なものです。つまり、このオブジェクトがコンテナに存在する場合は、このオブジェクトを取得します。 テストコードでは、実稼働コンテナ内にオブジェクトを作成する(作成されていない場合)だけ、既存のものを使用する必要はありません。プロダクションコードのみがオブジェクトをコンテナに追加/削除する必要があります。

MEF codeplex forumに投稿しましたが、応答はありません。だから、だれかのために答えがあるかもしれない。 また、拡張メソッドとしてその関数を記述する必要があるなら...それは答えとしても良いでしょう。

+0

あなたは単体テストで容器をテストしているように見えますか? –

+0

@MatthewAbbott - ViewModelレイヤー(ViewModelの最初のデザインで構築)でシステムテストを書こうとしています。これらは単体テストではありません... UI要素を操作する代わりに、コンテナに手を入れて、ビューモデルをつかんで同じ効果を得たいと思っています。 – Gishu

+0

ここをクリックしてください。http://caliburnmicro.codeplex.com/discussions/348548 – Gishu

答えて

1

私の解決策です。最初は、拡張メソッドの作成を試みました。私はいくつかのことを試み、文書を読んで、利用可能なプロパティ、イベント、メソッドをコンテナやカタログで調べましたが、何もできませんでした。

問題を考えた後、私が解決策を考え出すには、CompositionContainerに基づいた派生コンテナを作成し、GetButDoNotCreateメソッドを実装するしかありません。

更新:私は、ソリューションが単純な例でのみ動作し、GetExportedValueを使用して部品の単純な部品を検索することができます。 [Import]を持つ部品が作成されていない場合、[Import]がない部品のための単純なサービスロケータとしてコンテナを使用しない限り、それは、これまでで構成されているタイプを追跡するためにGetExportedValueメソッドをオーバーライドして、GetButNotCreateでの型の組成物を確認するためにこれを使用して動作

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

namespace GetButNotCreate 
{ 
    public class CustomContainer : CompositionContainer 
    { 
     private List<Type> composedTypes = new List<Type>(); 

     public CustomContainer(ComposablePartCatalog catalog) 
      : base(catalog) 
     { 
     } 

     public new T GetExportedValue<T>() 
     { 
      if (!composedTypes.Contains(typeof(T))) 
       composedTypes.Add(typeof(T)); 

      return base.GetExportedValue<T>(); 
     } 

     public T GetButDoNotCreate<T>() 
     { 
      if (composedTypes.Contains(typeof(T))) 
      { 
       return base.GetExportedValue<T>(); 
      } 

      throw new Exception("Type has not been composed yet."); 
     } 
    } 
} 

:ここ

は実装です。私はあなたの質問に言及したような例外を投げた。

もちろん、GetExportedValueのオーバーロードをオーバーライドする必要があります(使用しない限り、安全のためにオーバーライドします)。クラスを使用する場合は、他のコンストラクタやものを追加することもできます。この例では、それを動作させるために最小限の努力をしました。

using System.ComponentModel.Composition; 
using System.ComponentModel.Composition.Hosting; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System; 

namespace GetButNotCreate 
{ 
    public interface IInterface { } 

    [Export(typeof(IInterface))] 
    public class MyClass : IInterface 
    { 
    } 

    [TestClass] 
    public class UnitTest1 
    {  
     [TestMethod] 
     [ExpectedException(typeof(Exception), "Type has not been composed yet.")] 
     public void GetButNotCreate_will_throw_exception_if_type_not_composed_yet() 
     { 
      var catalog = new AssemblyCatalog(typeof(UnitTest1).Assembly); 
      CustomContainer container = new CustomContainer(catalog); 
      container.ComposeParts(this); 

      var test = container.GetButDoNotCreate<IInterface>(); 
     } 

     [TestMethod] 
     public void GetButNotCreate_will_return_type_if_it_as_been_composed() 
     { 
      var catalog = new AssemblyCatalog(typeof(UnitTest1).Assembly); 
      CustomContainer container = new CustomContainer(catalog); 
      container.ComposeParts(this); 

      var x = container.GetExportedValue<IInterface>(); 
      var y = container.GetButDoNotCreate<IInterface>(); 

      Assert.IsNotNull(y); 
      Assert.AreEqual(x, y); 
     } 
    } 
} 

それはタイプがエクスポートされていない場合GetButNotCreateが例外をスローすることを示しており、それが既にされている場合、それはこのタイプを返すこと:ここでは

は、新しいメソッドをテストするユニットテストです輸入された。

MEFが部品を構成しているかどうかを確認するために、どこにでもフックを見つけることができませんでしたので、このCustomContainerソリューションが私のベスト・ベットになります。

+0

@ Giles - この方法では、オブジェクトを構築してそれらを傍受するためのさまざまなMEFパスをすべて知っている必要があります。また、オブジェクトツリーが構築されている場合、これは根だけをトレースします。第二に、この仲介業者が部品のガベージコレクションを防止するかどうかは不明です。 – Gishu

+0

しかし、試み/努力のために+1。私は今、必要性を疑問視しています。たとえViewModelが(実動コードの代わりに)テストから(getExportedValueで)作成されたとしても、おそらく初期化/他の共同作業者に配線されないので、テストは失敗します。 – Gishu

+0

@ Gishu私の最初の投稿を投稿した後、イベントを扱ってみました。また、拡張メソッドを使って別の解決策を試みました。おそらくリフレクションを使用すると、MEFがその部分に使用している内部コレクションを見て、コレクションにすでにパーツが存在するかどうかを確認する拡張メソッドを作成できます。 – Gilles

0

コンテナに独自のラッパーを付ける価値はあると思います。 IContainerWrapperのようなものをあなたのコードのどこにでも使ってください。場所にこれを有する

  • あなたが通常のユニットテストを持っている場合は、単にあなたのニーズに合った、ラッパーの別のインスタンスを注入することができます。

  • プロダクションコンテナにアクセスするが、上記のような動作をする場合は、プロダクションラッパーの実装でプリプロセッサディレクティブを使用できます。

関連する問題