从Simple Injector容器

时间:2017-11-29 13:52:59

标签: c# dependency-injection simple-injector

this讨论之后,我还有一些遗留代码,而不是正确地做了DI已经通过应用程序的容器,我认为这是因为一些通用/工厂/动态代码意味着他们什么时候这样做,他们更容易通过容器而不是重写整个系统!

然后,他们在需要时从容器实例中获得所需的内容。即。

public class SomeStageInAPipeline :
{
    private readonly IBlobAccessClient _blobAccessClient;

    public SomeStageInAPipeline (Container container)
    {
        _blobAccessClient = container.GetInstance<IBlobAccessClient>();
    }

这是好的,直到我们有条件地注册实例的场景,即

container.RegisterConditional(typeof(IBlobAccessClient),
    Lifestyle.Singleton.CreateRegistration(
        () => new BlobAccessClient(srcConnectionString), container),
    c => c.Consumer.Target.Parameter.Name.Contains("src"));

container.RegisterConditional(typeof(IBlobAccessClient),
    Lifestyle.Singleton.CreateRegistration(
        () => new BlobAccessClient(destConnectionString), container),
    c => c.Consumer.Target.Parameter.Name.Contains("dest"));

我可以设置一个默认值,即

container.RegisterConditional(typeof(IBlobAccessClient),
    Lifestyle.Singleton.CreateRegistration(
        () => new BlobAccessClient(srcConnectionString), container),
    c => c.Handled == false);

适用于GetInstance(<IBlobAccessClient>)的现有请求,但我不知道如何访问其他“dest”实例,或者它是否可能。

更新我希望能够做的是:

public class SomeStageInAPipeline :
{
    private readonly IBlobAccessClient _srcBlobAccessClient;
    private readonly IBlobAccessClient _destBlobAccessClient;

    public SomeStageInAPipeline (Container container)
    {
        _srcBlobAccessClient = container.GetInstance<IBlobAccessClient>();
        // obviously the below just gets me the default instance
        _destBlobAccessClient = container.GetInstance<IBlobAccessClient>();
    }

1 个答案:

答案 0 :(得分:2)

根据其背景,注册是有条件的。但是,当您直接从Container解决时,您将丢失所有可能的上下文信息。已解析的类型将成为新的根类型。这是直接注入Containerreally bad idea的众多原因之一。

您可以注入某种Func<string, IBlobAccessClient>委托,但由于您已经对SomeStageInAPipeline进行了更改,因此直接重构为构造函数注入,如下所示:

public class SomeStageInAPipeline
{
    private readonly IBlobAccessClient _srcBlobAccessClient;
    private readonly IBlobAccessClient _destBlobAccessClient;

    public SomeStageInAPipeline(
        IBlobAccessClient srcBlobAccessClient,
        IBlobAccessClient destBlobAccessClient)
    {
        _srcBlobAccessClient = srcBlobAccessClient;
        _destBlobAccessClient = destBlobAccessClient;
    }
}

当您从SomeStageInAPipeline解析Container时,通过调用GetInstance<SomeStageInAPipeline>()或将其注入消费者,Simple Injector将为您构建包含这些条件的预期对象图。

<强>更新

如果此时无法更改SomeStageInAPipeline的构造函数签名,请考虑将IBlobAccessClient参数移动到参数对象中并从Container解析该参数对象:< / p>

public sealed class BlobAccessClients
{
    public readonly IBlobAccessClient Src;
    public readonly IBlobAccessClient Dest;

    public BlobAccessClients(IBlobAccessClient src, IBlobAccessClient dest)
    {
        this.Src = src;
        this.Dest = dest;
    }
}

这允许您将SomeStageInAPipeline更改为以下内容:

public class SomeStageInAPipeline
{
    private readonly IBlobAccessClient _srcBlobAccessClient;
    private readonly IBlobAccessClient _destBlobAccessClient;

    public SomeStageInAPipeline (Container container)
    {
        var clients = container.GetInstance<BlobAccessClients>();
        _srcBlobAccessClient = clients.Src;
        _destBlobAccessClient = clients.Dest;
    }
}