温莎为什么不解决我注册的每个装饰者?

时间:2013-01-19 18:43:15

标签: dependency-injection castle-windsor

我有一个课我想装饰两次。但是,当我解决这个类时,Windsor只修饰它一次而不是使用我的2个装饰器。我不确定为什么会这样,因为我在我正在解析的课程之前注册了两个装饰器,这就是我理解装饰器与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进行装饰。

1 个答案:

答案 0 :(得分: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;
    }
}

我承认不会直接尝试这一点,但是this blog表示它会起作用。

相关问题