2012-02-24 12 views
1

Calculatorはコンソールまたはウィンドウのメッセージボックスに結果を表示します。 IOutputServiceの1つのタイプがある場合は問題ありません。 ここでは、ConsoleOutputServiceMessageBoxOutputServiceの2種類があります。Unity IoCはインターフェイスと2つのタイプの2つのクラスを登録/解決します

コンストラクタで異なるタイプの2つの電卓を作成/登録し、実行時に電卓を使用するにはどうすればよいですか?


class Mockup 
{ 
    void Bootstrapping() 
    { 
     UnityContainer container = new UnityContainer(); 

     container.RegisterType<IInputService, ConsoleInputService>(); 
     container.RegisterType<IOutputService, ConsoleOutputService>("Console"); 
     container.RegisterType<IOutputService, MessageBoxOutputService>("Window"); 

     // expect with ConsoleOutputService 
     --> Pseudo code container.RegisterType<ICalculator, Calculator>("Cal1"); 
     // expect with MessageBoxOutputService 
     --> Pseudo code container.RegisterType<ICalculator, Calculator>("Cal2");** 
    } 

    void RunConsole() 
    { 
     ICalculator lp = container.Resolve<ICalculator>("Cal1"); 
     lp.Run(); 
    } 

    void RunWindow() 
    { 
     ICalculator lp = container.Resolve<ICalculator>("Cal2"); 
     lp.Run(); 
    } 
} 

public class Calculator : ICalculator 
{ 
    public Calculator(IInputService inputService, IOutputService outputService) 
    { 
     InputService = inputService; 
     OutputService = outputService; 
    } 
    public void Run() 
    {    
    } 
}  

答えて

0

まず第一に、あなたはあなたのアーキテクチャを再考することをお勧めします。たとえば、出力サービスを登録する前に、どのタイプのアプリケーションを使用するかを知るまで待ちます。それから、必要なものを登録するだけです。または、インダイレクションのレイヤーを追加して、別のサービスにOutputServiceを依頼すると、アプリがどのモードで実行されているかを知ることができます。

しかし、 2つのアプローチがあります。まず、InjectionConstructorに2つのResolvedParameterを使用します。これにより、使用する名前付き出力サービスを指定できます。ただし、Calculatorのコンストラクタをリファクタリングすると、実行時にしか見つからないため、脆弱です。

したがって、より良いアプローチはInjectionFactoryで、計算機オブジェクトを作成するFuncを与えます。 Funcはコンテナにアクセスできるので、名前付き解決を行うことができます。あなたが望むことを行う合格単位テストは次のとおりです。

[Test] 
public void NamedDependenciesTest() 
{ 
    IUnityContainer container = new UnityContainer(); 
    container.RegisterType<IInputService, ConsoleInputService>(); 
    container.RegisterType<IOutputService, ConsoleOutputService>("Console"); 
    container.RegisterType<IOutputService, MessageBoxOutputService>("Window"); 

    container.RegisterType<ICalculator>("Cal1", new InjectionFactory((c) => new Calculator(c.Resolve<IInputService>(), c.Resolve<IOutputService>("Console")))); 
    container.RegisterType<ICalculator>("Cal2", new InjectionFactory((c) => new Calculator(c.Resolve<IInputService>(), c.Resolve<IOutputService>("Window")))); 

    // alternative setup with ResolvedParameter: 
    //container.RegisterType<ICalculator, Calculator>("Cal1", new InjectionConstructor(new ResolvedParameter(typeof(IInputService)), new ResolvedParameter(typeof(IOutputService), "Console"))); 
    //container.RegisterType<ICalculator, Calculator>("Cal2", new InjectionConstructor(new ResolvedParameter(typeof(IInputService)), new ResolvedParameter(typeof(IOutputService), "Window"))); 

    var cal1 = container.Resolve<ICalculator>("Cal1"); 
    Assert.IsInstanceOf<ConsoleOutputService>(cal1.OutputService); 
    var cal2 = container.Resolve<ICalculator>("Cal2"); 
    Assert.IsInstanceOf<MessageBoxOutputService>(cal2.OutputService); 
} 

interface IInputService { } 
interface IOutputService { } 
interface ICalculator { IOutputService OutputService { get; } } 
class ConsoleInputService : IInputService { } 
class ConsoleOutputService : IOutputService { } 
class MessageBoxOutputService : IOutputService { } 
class Calculator : ICalculator 
{ 
    public Calculator(IInputService input, IOutputService output) { this.InputService = input; this.OutputService = output; } 

    public IInputService InputService { get; private set; } 
    public IOutputService OutputService { get; private set; } 
} 
+0

ありがとうございます。それは非常に有用です。 – DDrim

+0

それは私にとって非常に役に立ちます...ありがとう。 – DDrim

関連する問題