3

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

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 容器,它将用于SimpleRandomIntGeneratorforRandomArrayItemChooseCryptoServiceProviderRandomIntGeneratorfor LogInCodeGenerator

有没有办法用任何流行的 .NET IoC 容器来做到这一点?我对温莎城堡特别感兴趣。

4

4 回答 4

4

使用 Windsor 的服务覆盖。请参阅Windsor Docs中的“提供组件以供依赖项使用”部分。

于 2013-02-28T18:30:20.120 回答
3

然后我有两个客户不想知道特定的实现。

您的设计似乎有些模棱两可。这些客户可能对确切的实现不感兴趣,但您的系统中似乎有某种要求LogInCodeGenerator必须使用加密随机数。

由于这是系统安全的要求,因此最好在设计中明确说明这一点。换句话说,您在这里谈论的是两个单独的合同:

interface IRandomIntGenerator { }

interface ICryptographicRandomIntGenerator { }

这不仅使代码的意图更加清晰,而且从设计中消除这种歧义使您的 DI 配置更加简单。

于 2013-02-28T16:11:25.293 回答
1

您可以命名已注册的实例,然后通过它们的名称访问它们。在您的情况下,如果我理解您的问题,您需要基于请求已解析实例的类进行不同的注入。因此,您可以通过请求类的类型名称来命名您的注册实例。

您将不得不resolve手动处理您的实例:

IRandomIntGenerator generator = container.Resolve<IRandomIntGenerator>(GetType().Name);
于 2013-02-28T13:34:54.047 回答
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")),
于 2013-03-01T11:53:36.663 回答