7

我有一个具有 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<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(string name) 的工作方式中遗漏了一些基本的东西,但我认为它在容器中查找具有该名称的类型。

4

2 回答 2

7

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

        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" ) ) ) );

请注意,我使用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>( "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();
于 2013-04-24T07:15:22.237 回答
1

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

        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
于 2016-07-18T08:57:51.503 回答