将同一接口的不同实现和配置注入不同的客户端
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
实例。
ClassA
的所有实例(通过IClassA
实现和注册)需要一个单例FileStorage
,"C:\Temp\foo.txt"作为filePath
.
ClassB
的所有实例(通过IClassB
实现和注册)需要一个单例FileStorage
,"C:\Temp\bar.txt"作为filePath
.
ClassC
的所有实例(通过 IClassC
实现和注册)需要一个单例 HttpStorage
和 IHttpClient
的已注册单例。
如何在不退回到手动创建大部分依赖关系图的情况下实现上述目标?
每次您认为需要时要问的主要问题是:我是否违反了 Liskov Substitution Principle。万一实现不能互换,你就破坏了 LSP。如果在你向其中注入 HttpStorage
时 ClassA
中断,那么你正在破坏 LSP。在这种情况下,您应该为每个实现提供各自的抽象,例如 IFileStorage
和 IHttpStorage
.
我的第一印象是你没有违反 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 中的新内容。
假设我有一个接口 IStorage
和它的多个实现,例如:
class FileStorage : IStorage
{
public FileStorage(string filePath)
{
}
}
class HttpStorage : Storage
{
public HttpStorage(IHttpClient httpClient)
{
}
}
现在我有多个 类 我想在我的应用程序中注册,每个都需要一个不同的 IStorage
实例。
ClassA
的所有实例(通过IClassA
实现和注册)需要一个单例FileStorage
,"C:\Temp\foo.txt"作为filePath
.ClassB
的所有实例(通过IClassB
实现和注册)需要一个单例FileStorage
,"C:\Temp\bar.txt"作为filePath
.ClassC
的所有实例(通过IClassC
实现和注册)需要一个单例HttpStorage
和IHttpClient
的已注册单例。
如何在不退回到手动创建大部分依赖关系图的情况下实现上述目标?
每次您认为需要时要问的主要问题是:我是否违反了 Liskov Substitution Principle。万一实现不能互换,你就破坏了 LSP。如果在你向其中注入 HttpStorage
时 ClassA
中断,那么你正在破坏 LSP。在这种情况下,您应该为每个实现提供各自的抽象,例如 IFileStorage
和 IHttpStorage
.
我的第一印象是你没有违反 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 中的新内容。