【发布时间】:2014-05-08 19:16:58
【问题描述】:
我有一个带有query/handler based architecture 的应用程序。我有如下界面:
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
这个接口有很多非通用的实现。这些实现由通用装饰器包装,用于日志记录、分析、授权等。但有时我想根据装饰器的通用类型约束有条件地应用通用装饰器。以这个缓存装饰器为例,它只能应用于返回 ReadOnlyCollection<T> 的查询(仅仅是因为缓存任何可变的集合没有多大意义):
public class CachingQueryHandlerDecorator<TQuery, TResult>
: IQueryHandler<TQuery, ReadOnlyCollection<TResult>>
where TQuery : IQuery<ReadOnlyCollection<TResult>>
{
private readonly IQueryHandler<TQuery, ReadOnlyCollection<TResult>> decoratee;
private readonly IQueryCache cache;
public CachingQueryHandlerDecorator(
IQueryHandler<TQuery, ReadOnlyCollection<TResult>> decoratee,
IQueryCache cache)
{
this.decoratee = decoratee;
this.cache = cache;
}
public ReadOnlyCollection<TResult> Handle(TQuery query)
{
ReadOnlyCollection<TResult> result;
if (!this.cache.TryGetResult(query, out result))
{
this.cache.Store(query, result = this.decoratee.Handle(query));
}
return result;
}
}
更棘手的是,这些条件装饰器可能位于装饰器链中的任何位置。他们往往是中间的装饰者之一。例如,这个 CachingQueryHandlerDecorator 包装了一个非条件 ProfilingQueryHandlerDecorator 并且应该被一个条件 SecurityQueryHandlerDecorator 包装。
我发现this answer 是指有条件地应用非泛型装饰器;不是关于基于泛型类型约束有条件地应用泛型装饰器。我们如何使用 Autofac 中的通用装饰器来实现这一点?
【问题讨论】:
-
@JimBolla:这不是重复的 IMO。尽管两者都是关于有条件地处理泛型装饰器,但这个问题明确地与泛型类型约束有关,这很可能需要不同的方式来处理它们。
-
答案将完全相同...实现一个类似于原始问题中推荐的 IRegistrationSource。唯一的区别在于
if语句。哎呀,你可以让这个问题的实现和另一个共享一个通用的抽象基类。 -
@JimBolla:让我们等待尼克对此的看法。他答应我这个周末回答这些问题。
标签: c# generics dependency-injection ioc-container autofac