2013-04-23 18 views
5

私は、リポジトリとゲートウェイ(sms)の2つの依存関係を持つサービスを持っています。Unityとの名前付き依存関係の解決

ゲートウェイに渡されるパラメータの1つだけが異なる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<IRepository, Repository>() 
      .RegisterType<IGateway, Gateway>("FooGateway", new InjectionConstructor("I am foo")) 
      .RegisterType<IGateway, Gateway>("BarGateway", new InjectionConstructor("I am bar")) 
      .RegisterType<IServiceFoo, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("FooGateway"))) 
      .RegisterType<IServiceBar, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("BarGateway"))); 

     var barGateway = container.Resolve<IGateway>("BarGateway"); 
     var fooGateway = container.Resolve<IGateway>("FooGateway"); 

     var serviceBar = container.Resolve<IServiceBar>(); 
     var serviceBarGatewayName = serviceBar.DoSomething(); 

     var serviceFoo = container.Resolve<IServiceFoo>(); 
     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(文字列名)がどのように動作しているかの根本的なものを見逃していると思いますが、その名前のコンテナ内の型を探すと仮定しました。 (私が期待きたように)

+0

次のように、それはまたParameterOverrideを使用して行うことができますInjectionConstructorを使用して、ResolvedParameterの代わりに明示的なコードを持つようにします。これはうまくいくはずですが、これがあなたのバージョンではうまくいかない理由には答えられません。 –

+0

@WiktorZychla私はinjectionfactoryを試しましたが、その文脈では間違ったゲートウェイが解決されたにもかかわらず、同様の結果が得られました。私はこの簡単な例で朝にやり直して、結果をテストケースに更新します。 – drch

+0

明日もそれを試みます。それはここ10時ですので、私は朝に報告します。 –

答えて

5

はまだバージョンが動作しない理由はわかりませんが、これは、作業を行います。私はInjectionFactory代わりのInjectionConstructorを使用しています

 var container = new UnityContainer(); 
     container 
      .RegisterType<IRepository, Repository>() 
      .RegisterType<IGateway, Gateway>("FooGateway", new InjectionConstructor("I am foo")) 
      .RegisterType<IGateway, Gateway>("BarGateway", new InjectionConstructor("I am bar")) 
      //.RegisterType<IServiceFoo, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("FooGateway"))) 
      //.RegisterType<IServiceBar, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("BarGateway"))); 
      .RegisterType<IServiceFoo>(new InjectionFactory(c => new Service(c.Resolve<IRepository>(), c.Resolve<IGateway>("FooGateway")))) 
      .RegisterType<IServiceBar>(new InjectionFactory(c => new Service(c.Resolve<IRepository>(), c.Resolve<IGateway>("BarGateway")))); 

注意。

さらに別のバージョンが動作します。今回私は、サービスを登録するあなたの方法を保つが、私は彼らが命名作り、名前によって解決:

 var container = new UnityContainer(); 
     container 
      .RegisterType<IRepository, Repository>() 
      .RegisterType<IGateway, Gateway>("FooGateway", new InjectionConstructor("I am foo")) 
      .RegisterType<IGateway, Gateway>("BarGateway", new InjectionConstructor("I am bar")) 
      .RegisterType<IServiceFoo, Service>("sf", new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("FooGateway"))) 
      .RegisterType<IServiceBar, Service>("sb", new InjectionConstructor(new ResolvedParameter<IRepository>(), new ResolvedParameter<IGateway>("BarGateway"))); 
      //.RegisterType<IServiceFoo>(new InjectionFactory(c => new Service(c.Resolve<IRepository>(), c.Resolve<IGateway>("FooGateway")))) 
      //.RegisterType<IServiceBar>(new InjectionFactory(c => new Service(c.Resolve<IRepository>(), c.Resolve<IGateway>("BarGateway")))); 


     var barGateway = container.Resolve<IGateway>("BarGateway"); 
     var fooGateway = container.Resolve<IGateway>("FooGateway"); 

     var serviceBar = container.Resolve<IServiceBar>("sb"); 
     var serviceBarGatewayName = serviceBar.DoSomething(); 

     var serviceFoo = container.Resolve<IServiceFoo>("sf"); 
     var serviceFooGatewayName = serviceFoo.DoSomething(); 
+0

ありがとうございました - 私は同じ結果で早くinjectionfactoryを試みましたが、間違ったことをしたに違いありません。 – drch

+0

* sigh *これは質問からのテストでは解決しましたが、実際のテスト(偽物を使ってこの正確な設定に単純化されました)に対して私がテストに移ったとき、InjectionFactoryのアプローチは私の元の問題と同じように動作しました。私は2番目の解決策として指摘したように.Resolve()で名前を使用することに固執していると思います。乾杯。 – drch

+0

私があなたの場合、私は自分のコードプレックスサイトで問題をオープンします。これは予想外の動作であり、何とか修正される可能性があります。あなたのコードを見ているだけで、おそらく誰もそれが動作しないと思うでしょう。一方で、彼らが提出を拒否すれば、少なくとも彼らは何とか間違っていることを何とか説明するでしょう。 –

1

回避策はInjectionFactoryを使う代わりにすることができ

 container 
      .RegisterType<IRepository, Repository>() 
      .RegisterType<IGateway, Gateway>("FooGateway", new InjectionConstructor("I am foo")) 
      .RegisterType<IGateway, Gateway>("BarGateway", new InjectionConstructor("I am bar")) 
      .RegisterType<IServiceFoo, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), typeof(IGateway))) 
      .RegisterType<IServiceBar, Service>(new InjectionConstructor(new ResolvedParameter<IRepository>(), typeof(IGateway))); 

     var barGateway = container.Resolve<IGateway>("BarGateway"); 
     var fooGateway = container.Resolve<IGateway>("FooGateway"); 

     var serviceBar = container.Resolve<IServiceBar>(new ParameterOverride("gateway", barGateway)); 
     var serviceBarGatewayName = serviceBar.DoSomething(); 

     var serviceFoo = container.Resolve<IServiceBar>(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 
関連する問題