2012-01-24 2 views
2

私はMEFを使用して、異なるタイプのコンストラクタ引数を持つ同じタイプのアイテムを作成できますか?

  • IOne
  • ITwo
  • IThree
  • ICalcalculator

そしてそれらのいくつかの実装

    を持って定義された次のインタフェースを持っています
  • ClassOne: IOne
  • ClassTwo: IOne
  • ClassThree : ITwo
  • ClassFour : ITwo
  • ClassFive: IThree
  • MyCalc : ICalculator

MyCalcはクラス1-4、しかし2つのClassOneのインスタンスと初期化即ちとして区別ClassThreeを必要

public MyCalc(){ 
    ClassOne first= new ClassOne("filePath1"); 
    ClassOne second = new ClassOne("filePath2"); 
    ClassThree third = new ClassThree ("filePath3"); 
    ClassThree fourth = new ClassThree ("filePath4"); 
} 

私はMEFを使用してMyCalcを作成しようとしています。上記の例では、filePathXは設定ファイルに含まれています。私はこれまでに以下のことを行ってきましたが、それはうまくいくように見えますが、現在の方法とアプローチが正しくないと感じています。このアプローチを見ると、私は名前(ValDatePrices & EDDatePrices)に縛られていますが、私の現在のアプローチ(上記を参照)よりもクリーンではありません。

異なるctor引数を持つ同じタイプの複数のオブジェクトを読み込むには、よりクリーンな方法がありますか?

public class MyCalc: ICalculator 
{ 
    private CompositionContainer container; 

    public MyCalc() 
    { 
     var catalog = new AggregateCatalog(); 
     catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyCalc).Assembly)); 

     container = new CompositionContainer(catalog); 

     try 
     { 

     this.container.ComposeExportedValue<ClassFive>(
       new ClassFive((ConfigurationManager.AppSettings["SomePath"]))); 
     this.container.ComposeExportedValue<ClassOne>(
       "ValDatePrices" 
       , new ClassOne((ConfigurationManager.AppSettings["filePath1"]))); 
     this.container.ComposeExportedValue<ClassOne>(
       "EDDatePrices" 
       , new ClassOne((ConfigurationManager.AppSettings["filePath2"]))); 

     this.container.ComposeParts(this); 

     } 
     catch (CompositionException compositionException) 
     { 
      Console.WriteLine(compositionException.ToString()); 
     } 

    } 

    [Import("ValDatePrices")] 
    public ClassOne ValDatePrices; 

    [Import("EDDatePrices")] 
    public ClassOne EDDatePrices; 

    [Import] 
    public ClassFive SPointReader; 

    public void Calculate() 
    { 

     Console.WriteLine(SPointReader.Result); 
     Console.WriteLine(ValDatePrices.Result.Count); 
     Console.WriteLine(EDDatePrices.Result.Count); 

     Console.ReadKey(); 
    } 
} 

使用

class Program 
{ 
    static void Main(string[] args) 
    { 
     var p = new MyCalc(); 
     p.Calculate(); 
    } 
} 
} 

サイド質問:MyCalcコンストラクタ内のコードを配置すべきですか?

答えて

1

適切なDI/IoCコンテナの使用を検討しましたか?これは、例えば、 NInjectまたはStructureMap

これはNInjectでどのように実装できるかの例です。これを行う方法は数多くあることに注意してください。チュートリアルを参照して、必要に応じてNInjectを入手する必要があります。

MyCalculator

public class MyCalculator : ICalculator 
{ 
    private IOne _oneFirst; 
    private IOne _oneSecond; 
    private ITwo _twoFirst; 
    private ITwo _twoSecond; 
    private IThree _three; 


    public MyCalculator([Named("Val")] IOne oneFirst, [Named("ED")] IOne oneSecond, 
         [Named("Val")] ITwo twoFirst, [Named("ED")] ITwo twoSecond, IThree three) 
    { 
     _oneFirst = oneFirst; 
     _oneSecond = oneSecond; 
     _twoFirst = twoFirst; 
     _twoSecond = twoSecond; 
     _three = three; 

    } 

    public void Calculate() 
    { 

    } 
} 

カーネル

public class CalculatorModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IOne>().ToMethod(CreateOne).Named("Val"); 
     Bind<IOne>().ToMethod(CreateTwo).Named("ED"); 
     Bind<ITwo>().ToMethod(CreateThree).Named("Val"); 
     Bind<ITwo>().ToMethod(CreateFour).Named("ED"); 
     Bind<IThree>().To<ClassFive>(); 
     Bind<ICalculator>().To<MyCalculator>(); 

    } 

    private ITwo CreateFour(IContext arg) 
    { 
     return new ClassFour(); 
    } 

    private ITwo CreateThree(IContext arg) 
    { 
     return new ClassThree(); 
    } 

    private IOne CreateOne(IContext context) 
    { 
     return new ClassOne("filePath1"); 
    } 

    private IOne CreateTwo(IContext arg) 
    { 
     return new ClassTwo("filePath2"); 
    } 


} 

カーネルについての注意:あなたが好きなら方法はラムダ関数に短縮することが可能と命名された属性をパラメータに置き換えることができ名前またはカスタム属性。 Contextual Binding

使用

class Program 
{ 
    static void Main(string[] args) 
    { 
     StandardKernel kernel = new StandardKernel(new CalculatorModule()); 
     var cal = kernel.Get<ICalculator>(); 
     cal.Calculate(); 
    } 
} 
+0

がよさそうだ参照してください、前にこのようにそれについて考えたことはありません - しかしMEFベースのソリューションを探して、それと作品を試みたが、最終的な目標は、これらのアイデアを包含することであるので、 WPF/Prismベースのアプリケーション – Ahmad

+0

MEFを使用する特別な理由はありますか? NInjectは、MEFが行うことができるすべてのことを行うことができます。財産の輸入/注射、マルチインジェクションなどのようなものです。私は、WPFとほとんどの場合、Prismよりはるかに優れたオプションと互換性があると言います。シンプルでありながら強力です:) – edvaldig