我想知道如何在不同的客户端中使用一个接口的不同实现。这是一个示例情况。
public interface IRandomIntGenerator
{
int Generate();
}
public class SimpleRandomIntGenerator : IRandomIntGenerator
{
public int Generate()
{
return new Random().Next();
}
}
public class CryptoServiceProviderRandomIntGenerator : IRandomIntGenerator
{
public int Generate()
{
var generator = new RNGCryptoServiceProvider();
byte[] bytes = new byte[4];
generator.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
}
然后我有两个不想了解特定实现的客户端。一个生成登录代码,另一个选择数组的随机项。
public class LogInCodeGenerator
{
private readonly IRandomIntGenerator randomIntGenerator;
public LogInCodeGenerator(IRandomIntGenerator randomIntGenerator)
{
this.randomIntGenerator = randomIntGenerator;
}
public string GenerateCode(int length)
{
var builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
builder.Append(randomIntGenerator.Generate() % 10);
return builder.ToString();
}
}
public class RandomArrayItemChoose
{
private readonly IRandomIntGenerator randomIntGenerator;
public RandomArrayItemChoose(IRandomIntGenerator randomIntGenerator)
{
this.randomIntGenerator = randomIntGenerator;
}
public string Choose(string[] arr)
{
return arr[randomIntGenerator.Generate() % arr.Length];
}
}
我想以这样的方式配置IoC容器:SimpleRandomIntGenerator
使用RandomArrayItemChoose
而CryptoServiceProviderRandomIntGenerator
使用LogInCodeGenerator
。
有没有办法在任何流行的IoC容器中执行此操作?我对温莎城堡特别感兴趣。
答案 0 :(得分:4)
使用Windsor的服务覆盖。请参阅Windsor Docs中的“为要使用的依赖项提供组件”部分。
答案 1 :(得分:3)
然后我有两个不想了解特定的客户 的实施方式。
您的设计似乎有些含糊不清。这些客户可能对确切的实现不感兴趣,但是在您的系统中似乎有某种要求LogInCodeGenerator
必须使用加密随机数。
由于这是系统安全的要求,因此最好使设计明确这一点。换句话说,你在这里谈论两个单独的合同:
interface IRandomIntGenerator { }
interface ICryptographicRandomIntGenerator { }
这不仅使代码的意图更加清晰,从设计中消除这种模糊性使得DI配置更加简单。
答案 2 :(得分:1)
您可以为已注册的实例命名,然后按名称访问它们。 在您的情况下,如果我理解您的问题,您需要基于请求已解析实例的类进行不同的注入。 因此,您可以按请求类的类型名称命名已注册的实例。
您必须手动resolve
您的实例:
IRandomIntGenerator generator = container.Resolve<IRandomIntGenerator>(GetType().Name);
答案 3 :(得分:1)
只需显式声明依赖项:
Component.
For<IRandomIntGenerator>().
ImplementedBy<SimpleRandomIntGenerator>().
Named("SimpleRandomIntGenerator"),
Component.
For<IRandomIntGenerator>().
ImplementedBy<CryptoServiceProviderRandomIntGenerator>().
Named("CryptoServiceProviderRandomIntGenerator"),
Component.
For<RandomArrayItemChoose>().
DependsOn(Dependency.
OnComponent("randomIntGenerator", "SimpleRandomIntGenerator")),
Component.
For<LogInCodeGenerator>().
DependsOn(Dependency.
OnComponent("randomIntGenerator", "CryptoServiceProviderRandomIntGenerator")),