我有一个课我想装饰两次。但是,当我解决这个类时,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
进行装饰。
答案 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表示它会起作用。