2012-02-24 69 views
1

我有Calculator顯示在控制檯或窗口消息框的結果。 如果我有一個類型爲IOutputService,則不存在問題。 現在,我有兩種類型 - ConsoleOutputServiceMessageBoxOutputService統一IoC註冊/解析兩個類與接口和兩種

如何在構造函數中創建/註冊具有不同類型的兩個計算器並在運行時使用計算器?


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,並且可以知道你的應用程序運行在什麼模式。

但是你要求做的事情是可能的。有兩種方法。首先是使用InjectionConstructorResolvedParameter兩個 - 這可讓您指定要使用的指定輸出服務。然而,它很脆弱,因爲如果你重構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 2012-03-06 16:46:12

+0

這對我很有幫助...謝謝。 – DDrim 2012-03-19 16:57:05