我有Calculator
在控制台或窗口消息框上显示结果。
如果IOutputService
有一种类型,则没有问题。
现在,我有两种类型 - ConsoleOutputService
和MessageBoxOutputService
。
如何在构造函数中创建/注册两个具有不同类型的计算器,并在运行时使用计算器?
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 :(得分:0)
首先,您可能想重新考虑您的架构。例如,如何在注册输出服务之前等到知道自己的应用程序类型。然后你可以注册你需要的那个。或者你可以添加一个额外的间接层,要求另一个服务来获取OutputService,并且可以知道你的应用运行的模式。
但你要求的是团结一致。有两种方法。首先是使用InjectionConstructor
和两个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; }
}