使用Unity解析命名依赖项

我有一个具有2个依赖项的服务:存储库和网关(短信)。

我需要解析2个不同版本的服务,这些版本仅在传递给网关的其中一个参数上有所不同。

代码简化如下

public interface IService { string DoSomething(); } public interface IServiceFoo { string DoSomething(); } public interface IServiceBar { string DoSomething(); } public interface IRepository { } public class Repository : IRepository { } public interface IGateway { string Name { get; set; } } public class Gateway : IGateway { public string Name { get; set; } public Gateway(string name) { this.Name = name; } } public class Service : IService, IServiceFoo, IServiceBar { private readonly IGateway _gateway; private readonly IRepository _repo; public Service(IRepository repo, IGateway gateway) { _gateway = gateway; _repo = repo; } public string DoSomething() { return _gateway.Name; } } 

测试失败

 [TestClass] public class UnityTest { [TestMethod] public void TestMethod1() { var container = new UnityContainer(); container .RegisterType() .RegisterType("FooGateway", new InjectionConstructor("I am foo")) .RegisterType("BarGateway", new InjectionConstructor("I am bar")) .RegisterType(new InjectionConstructor(new ResolvedParameter(), new ResolvedParameter("FooGateway"))) .RegisterType(new InjectionConstructor(new ResolvedParameter(), new ResolvedParameter("BarGateway"))); var barGateway = container.Resolve("BarGateway"); var fooGateway = container.Resolve("FooGateway"); var serviceBar = container.Resolve(); var serviceBarGatewayName = serviceBar.DoSomething(); var serviceFoo = container.Resolve(); var serviceFooGatewayName = serviceFoo.DoSomething(); Assert.AreEqual("I am bar", barGateway.Name); // pass Assert.AreEqual("I am foo", fooGateway.Name); // pass Assert.AreEqual("I am bar", serviceBarGatewayName); // pass Assert.AreEqual("I am foo", serviceFooGatewayName); // FAIL 

解析服务时传入错误的网关,但是如果我通过名称明确解析网关,则说明正确。 我认为我在ResolvedParameter(字符串名称)的工作方式上缺少一些基本的东西,但我认为它在容器中查找具有该名称的类型。

仍然不知道为什么你的版本不起作用,但这可行(正如我所料):

  var container = new UnityContainer(); container .RegisterType() .RegisterType( "FooGateway", new InjectionConstructor( "I am foo" ) ) .RegisterType( "BarGateway", new InjectionConstructor( "I am bar" ) ) //.RegisterType( new InjectionConstructor( new ResolvedParameter(), new ResolvedParameter( "FooGateway" ) ) ) //.RegisterType( new InjectionConstructor( new ResolvedParameter(), new ResolvedParameter( "BarGateway" ) ) ); .RegisterType( new InjectionFactory( c => new Service( c.Resolve(), c.Resolve( "FooGateway" ) ) ) ) .RegisterType( new InjectionFactory( c => new Service( c.Resolve(), c.Resolve( "BarGateway" ) ) ) ); 

请注意,我使用的是InjectionFactory而不是InjectionConstructor

还有另一个版本可行。 这次我保留了注册服务的方式,但我将它们命名并按名称解析:

  var container = new UnityContainer(); container .RegisterType() .RegisterType( "FooGateway", new InjectionConstructor( "I am foo" ) ) .RegisterType( "BarGateway", new InjectionConstructor( "I am bar" ) ) .RegisterType( "sf", new InjectionConstructor( new ResolvedParameter(), new ResolvedParameter( "FooGateway" ) ) ) .RegisterType( "sb", new InjectionConstructor( new ResolvedParameter(), new ResolvedParameter( "BarGateway" ) ) ); //.RegisterType( new InjectionFactory( c => new Service( c.Resolve(), c.Resolve( "FooGateway" ) ) ) ) //.RegisterType( new InjectionFactory( c => new Service( c.Resolve(), c.Resolve( "BarGateway" ) ) ) ); var barGateway = container.Resolve( "BarGateway" ); var fooGateway = container.Resolve( "FooGateway" ); var serviceBar = container.Resolve( "sb" ); var serviceBarGatewayName = serviceBar.DoSomething(); var serviceFoo = container.Resolve( "sf" ); var serviceFooGatewayName = serviceFoo.DoSomething(); 

它也可以使用ParameterOverride完成,如下所示

  container .RegisterType() .RegisterType("FooGateway", new InjectionConstructor("I am foo")) .RegisterType("BarGateway", new InjectionConstructor("I am bar")) .RegisterType(new InjectionConstructor(new ResolvedParameter(), typeof(IGateway))) .RegisterType(new InjectionConstructor(new ResolvedParameter(), typeof(IGateway))); var barGateway = container.Resolve("BarGateway"); var fooGateway = container.Resolve("FooGateway"); var serviceBar = container.Resolve(new ParameterOverride("gateway", barGateway)); var serviceBarGatewayName = serviceBar.DoSomething(); var serviceFoo = container.Resolve(new ParameterOverride("gateway", fooGateway)); var serviceFooGatewayName = serviceFoo.DoSomething(); Assert.AreEqual("I am bar", barGateway.Name); // pass Assert.AreEqual("I am foo", fooGateway.Name); // pass Assert.AreEqual("I am bar", serviceBarGatewayName); // pass Assert.AreEqual("I am foo", serviceFooGatewayName); // pass