将同一接口的不同实现和配置注入不同的客户端

injecting different implementations and configurations of same interface into different clients

假设我有一个接口 IStorage 和它的多个实现,例如:

class FileStorage : IStorage
{
    public FileStorage(string filePath)
    {            
    }
}

class HttpStorage : Storage
{
    public HttpStorage(IHttpClient httpClient)
    {
    }
}

现在我有多个 类 我想在我的应用程序中注册,每个都需要一个不同的 IStorage 实例。

如何在不退回到手动创建大部分依赖关系图的情况下实现上述目标?

每次您认为需要时要问的主要问题是:我是否违反了 Liskov Substitution Principle。万一实现不能互换,你就破坏了 LSP。如果在你向其中注入 HttpStorageClassA 中断,那么你正在破坏 LSP。在这种情况下,您应该为每个实现提供各自的抽象,例如 IFileStorageIHttpStorage.

我的第一印象是你没有违反 LSP。 Simple Injector v3 包含一个 RegisterConditional 方法,允许您进行条件注册。使用 Simple Injector v3.1 您可以进行如下注册:

Lifestyle transient = Lifestyle.Transient;

container.RegisterConditional(typeof(IStorage),
    transient.CreateRegistration(() => new FileStorage(@"C:\Temp\foo.txt"), container),
    c => c.Consumer.ImplementationType == typeof(ClassA));

container.RegisterConditional(typeof(IStorage),
    transient.CreateRegistration(() => new FileStorage(@"C:\Temp\bar.txt"), container),
    c => c.Consumer.ImplementationType == typeof(ClassB));

container.RegisterConditional(typeof(IStorage),
    transient.CreateRegistration(() => new HttpStorage(new HttpClient()), container),
    c => c.Consumer.ImplementationType == typeof(ClassC));

接受 Registration 实例的 RegisterConditional 重载是 v3.1 中的新内容。