3

異なるクライアントで 1 つのインターフェイスの異なる実装を使用する方法を考えています。これが状況の例です。

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);
    }
}

次に、特定の実装について知りたくない2人のクライアントがいます。1 つはログイン コードを生成し、もう 1 つは配列のランダムな項目を選択します。

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];
    }
}

SimpleRandomIntGeneratorforRandomArrayItemChooseCryptoServiceProviderRandomIntGeneratorfor を使用するように IoC コンテナーを構成したいと考えていますLogInCodeGenerator

.NET の一般的な IoC コンテナーでこれを行う方法はありますか? 特にウィンザー城に興味があります。

4

4 に答える 4

4

Windsor のサービス オーバーライドを使用します。Windsor Docsの「使用する依存関係のコンポーネントを提供する」セクションを参照してください。

于 2013-02-28T18:30:20.120 に答える
3

次に、特定の実装について知りたくない2人のクライアントがいます。

あなたのデザインにはあいまいさがあるようです。LogInCodeGeneratorこれらのクライアントは正確な実装には関心がないかもしれませんが、システムには暗号乱数を処理する必要があるような要件があるようです。

これはシステムを安全にするための要件であるため、設計でこれを明示することをお勧めします。つまり、ここでは 2 つの別個の契約について話しているのです。

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 に答える