如何在IoC容器中使用不同位置的不同实现

时间:2013-02-28 13:16:52

标签: c# .net castle-windsor ioc-container

我想知道如何在不同的客户端中使用一个接口的不同实现。这是一个示例情况。

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使用RandomArrayItemChooseCryptoServiceProviderRandomIntGenerator使用LogInCodeGenerator

有没有办法在任何流行的IoC容器中执行此操作?我对温莎城堡特别感兴趣。

4 个答案:

答案 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")),