我正在尝试使用Autofac构建一个查询管道,但似乎无法弄清楚如何正确地装饰它。工作流程
从缓存中检索>从DB中检索>存储在缓存中>变换
以下是当前配置
builder.RegisterAssemblyTypes(assemblies)
.Where(x => x.Name.EndsWith("Transform"))
.As(o => o.GetInterfaces()
.Where(i => i.IsClosedTypeOf(typeof(IQuery<,>)))
.Select(i => new KeyedService("Transform", i))
);
builder.RegisterGenericDecorator(
typeof(SaveToCache<,>),
typeof(IQuery<,>),
fromKey: "Transform",
toKey: "SaveCache"
);
builder.RegisterDecorator<IQuery<GetPerson, PersonDto>>(
(x, decorator) => new GetPersonQuery(decorator),
fromKey: "SaveCache",
toKey: "QueryDb"
);
builder.RegisterGenericDecorator(
typeof(RetrieveFromCache<,>),
typeof(IQuery<,>),
fromKey: "QueryDb"
);
因此链条有效,但下面的注册并不理想,因为新查询需要手动注册
builder.RegisterDecorator<IQuery<GetPerson, PersonDto>>(
(x, decorator) => new GetPersonQuery(decorator),
fromKey: "SaveCache",
toKey: "QueryDb"
);
那么无论如何使用某种形式的扫描机制来注册装饰器?
我想你可以扫描程序集并找到具体的实现然后注册它,但它仍然不那么直接:(
var type = typeof(IQuery<,>);
var queries = assemblies
.SelectMany(x => x.GetTypes())
.Where(y => y.GetInterfaces().Any(z => z.IsGenericType && z.GetGenericTypeDefinition() == type) && y.Name.EndsWith("Query"));
foreach (var query in queries)
{
// ?
}