1

ウィンザーにランダムな数のデコレーターで実装をラップするように強制しようとしているときに、次のことに遭遇しました。

私は3つのデコレータと実装をすべて同じインターフェースを使用しています。

このコードを実行すると、windsor は として解決icommandhandler<stringcommand>されますimplementation。これは、私が知る限り、予想される動作です。これは、型付き実装をオープン型付きデコレーターに登録できないためです。

ただし、行のコメントを外すと、container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());3 つのデコレータすべてが を解決するために使用されますimplementation。これは望ましい結果です (: の並べ替え)。

class Program
{
    static void Main(string[] args)
    {
        var container = new WindsorContainer();

        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));

        //uncomment the line below and watch the magic happen
        //container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
        container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());

        var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
        var command = new stringCommand();
        stringCommandHandler.Handle(command);

        Console.WriteLine(command.s);
        Console.ReadKey();
    }
}

public interface ICommandHandler<T>
{
    void Handle(T t);
}

public class stringCommand
{
    public string s { get; set; }
}

public abstract class Decorator<T> : ICommandHandler<T>
{
    public abstract void Handle(T t);
};

public class Decorator1<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator1(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator1;";
        _handler.Handle(t);
    }
}

public class Decorator2<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator2(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator2;";
        _handler.Handle(t);
    }
}
public class Decorator3<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator3(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator3;";
        _handler.Handle(t);
    }
}

public class implementation : ICommandHandler<stringCommand>
{
    public void Handle(stringCommand t)
    {
        t.s += "implementation;";
    }
}

なぜこれが起こっているのですか、これは私が気付いていないウィンザーの機能ですか? 同じ効果を達成するための別の方法はおそらくありますか?(リフレクションに頼ることなく)

4

1 に答える 1

1

windsor がコンポーネントを解決しようとするとき、最初により具体的なインターフェイスを解決しようとします。したがって、Component.For を登録すると、開いているジェネリック型よりもこれを解決することが優先されます。

同じインターフェイスが複数回登録されている場合は、最初に指定されたインターフェイスが使用されます。

したがって、この行のコメントを外さないと、これが最も具体的なコンポーネントであるため、アプリケーションは実装を解決します。

コメントを外すと、行 decorator1 が解決され、実際に魔法が始まります。デコレーターは、コンストラクターを満たす最初の登録済みコンポーネントの検索を開始します。この場合は、decorator1 になります (出力に decorator1 が 2 回表示されることに気付きましたか?)。実際の実装になるまで、次に登録されたコンポーネントなどを解決します。

したがって、私が考えることができる唯一のことは、decorator1 をオープンジェネリックとして登録するのではなく、特定のタイプとして登録することです。

よろしく、マルウェイン。

于 2013-06-14T07:53:30.127 に答える