11

これは簡単かもしれませんが、インターネットで検索するだけで頭が痛くなります

ここに問題があります:

interface IValidator
{
    void Validate(object obj);
}

public class ValidatorA : IValidator
{
    public void Validate(object obj) { }
}

public class ValidatorB : IValidator
{
    public void Validate(object obj) { }
}


interface IClassA { }
interface IClassB { }

public class MyBaseClass
{
    protected IValidator validator;

    public void Validate()
    {
        validator.Validate(this);
    }
}

public class ClassA : MyBaseClass, IClassA
{
    //problem: validator should ValidatorA
    public ClassA(IValidator validator) { }
}

public class ClassB : MyBaseClass, IClassB
{
    //problem: validator should ValidatorB
    public ClassB(IValidator validator) { }
}

public class OtherClass
{
    public OtherClass(IClassA a, IClassB b) { }
}


//on Main
var oc = container.Resolve<OtherClass>();

何か案が?

編集

ValidatorA私はandValidatorBを登録しましたがNamed、Castle Windsor がこれらのバリデータをClassAandClassBに適切に注入する方法が問題になりました。それを行う方法はありますか? またはより良い解決策はありますか?

私のクラスの設計が間違っていると思う人がいたら、アドバイスをお待ちしています。これまでのところ、私はそれが正しいと思います。はい、バリデーターには特定のクラスの特定の構成があります。しかし、それが抽象化されている理由があります:

  1. バリデーターは複雑なオブジェクトであり、データベースに接続する必要がある場合があるため、単体テストの理由から、実装ではなくインターフェイスをコンストラクターに渡す必要があります。
  2. 私が使用した唯一の方法はValidate
  3. MyBaseClass.Validate()よくあるテンプレートメソッドのパターンだと思いますよね?
4

2 に答える 2

12

選択したアーキテクチャの詳細には立ち入らず、Windsor コンテナーの構成だけに注目します。

特定のインターフェイス ( ) に複数の名前付き実装を登録した場合、 を使用してコンシューマー クラス ( 、) をIValidator登録するときに、どれを使用するかを指定できます。ClassAClassBServiceOverrides

次のコンテナー構成プロバイダーは、OtherClassを持つClassAインスタンスValidatorAおよびを持つClassBインスタンスValidatorB:

var container = new WindsorContainer();

container.Register(Component.For<IClassA>().ImplementedBy<ClassA>()
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorA")));
container.Register(Component.For<IClassB>().ImplementedBy<ClassB>()
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorB")));

container.Register(Component.For<IValidator>().ImplementedBy<ValidatorA>()
    .Named("ValidatorA"));
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorB>()
    .Named("ValidatorB"));

container.Register(Component.For<OtherClass>().ImplementedBy<OtherClass>());

var oc = container.Resolve<OtherClass>();
于 2012-07-04T15:10:03.503 に答える
2

ClassAタイトなカップル ( with ValidatorAClassBwith ValidatorB) を独立した型として共通のコンテナーに入れようとしているようです。これは無意味です。このような密結合に依存する必要がある場合は、この点で依存性注入を忘れて、型をハード参照するだけです。

すべてのクラスに共通のバリデーターを実装できれば、これはより理にかなっています。たとえば、クラスに検証ルールを提供する責任を負わせValidator 、ルールを強制するだけにします。または、クラス内にバリデーション全体を含めることもできます。これはおそらく、ここで最も賢明なシナリオです。

MyBaseClass.Validate()コントロールの反転のように見えますが、テンプレート メソッドとは異なります。

于 2012-07-04T12:04:39.287 に答える