0

2回飾りたいクラスがあります。ただし、このクラスを解決すると、Windsor は 2 つのデコレーターを使用する代わりに 1 回だけ装飾します。解決しているクラスの前に両方のデコレータを登録したため、これが当てはまる理由はわかりません。これが、デコレータがWindsorで動作することを理解する方法です。

これが私のコードです。

public interface IQueryExecuter
{
    TReturn Execute<TReturn>(IQuery<TReturn> query);
}

public class QueryLoggingDecorator : IQueryExecuter
{
    private ILogger _logger = NullLogger.Instance;

    public ILogger Logger
    {
        set { _logger = value; }
    }

    public TReturn Execute<TReturn>(IQuery<TReturn> query)
    {
        _logger.Info("Before query execute");
        var queryResults = query.Execute();
        _logger.Info("After query execute");

        return queryResults;
    }
}

public class QueryTransactionDecorator : IQueryExecuter
{
    public TReturn Execute<TReturn>(IQuery<TReturn> query)
    {
        try
        {
            Console.WriteLine("Beginning transaction");
            var queryResults = query.Execute();
            Console.WriteLine("Comitting transaction");

            return queryResults;
        }
        catch (Exception)
        {
            Console.WriteLine("Rolling back transaction");
            throw;
        }
    }
}

public interface IQuery<out TReturn>
{
    TReturn Execute();
}

public class Query : IQuery<string>
{
    public string Execute()
    {
        Console.WriteLine("Executing query");

        var queryResults = Path.GetRandomFileName();

        return queryResults;
    }
}

これが私のウィンザー登録コードです。

public class DefaultInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component
            .For<IQueryExecuter>()
            .ImplementedBy<QueryLoggingDecorator>()
            .LifestyleTransient());
        container.Register(Component
            .For<IQueryExecuter>()
            .ImplementedBy<QueryTransactionDecorator>()
            .LifestyleTransient());
        container.Register(Component
            .For<IQueryExecuter>()
            .ImplementedBy<QueryExecuter>()
            .LifestyleTransient());
    }
}

そして最後に、これが私の呼び出しコードです。

var container = new WindsorContainer();

container.Install(FromAssembly.This());

var queryExecuter = container.Resolve<IQueryExecuter>();
var queryResults = queryExecuter.Execute(new Query());

私は何が欠けていますか?

解決するIQueryExecuterと、ウィンザーが で装飾されQueryLoggingDecorator、次にQueryTransactionDecorator.

4

1 に答える 1

5

問題は、これらがデコレータではないことです。それらは、同じインターフェースの単なる異なる実装です。デコレータには、実際にデコレートするものが必要です。これは、実装しているのと同じインターフェイスのインスタンスであるため、チェーン内の次のデコレータを呼び出すことができます。

IQueryExecuterへの注入可能な参照を設定する必要があります。その後、Windsorが残りを処理し、登録された順序でデコレータチェーンを注入します(少なくともドキュメントによると)。

例えば:

public class QueryLoggingDecorator : IQueryExecuter
{
    private ILogger _logger = NullLogger.Instance;
    private IQueryExecuter innerExecuter;

    public QueryLoggingDecorator(IQueryExecuter innerExecuter)
    {
        this.innerExecuter = innerExecuter;
    }


    public ILogger Logger
    {
        set { _logger = value; }
    }

    public TReturn Execute<TReturn>(IQuery<TReturn> query)
    {
        _logger.Info("Before query execute");
        var queryResults = innerExecuter.Execute(query);
        _logger.Info("After query execute");

        return queryResults;
    }
}

私はこれを直接試さないことを認めますが、このブログはそれがうまくいくことを示しました。

于 2013-01-19T23:50:10.897 に答える