嵌套装饰对象,中间有一个工厂
Nested Decoratee with a Factory in between
我们有一个由 3 个 decoratee 组成的层次结构,实现了如下接口:
public interface IRetrieve
{
List<Widget> Retrieve(List<long> ids);
}
我们正在尝试使用以下模式:
- RetrieveBatcher : IRetriever // 将调用批量化为更小的尺寸
- RetrieveTimer : IRetriever // 确保检索在一个时间间隔后超时
- RetrieveCore : IRetriever // 执行实际的检索
运行时代码如下所示:
RetrieveBatcher(装饰器)
class RetrieveBatcher : IRetriever
{
Func<IRetriever> _decoratee;
public RetrieveBatcher(Func<IRetriever> decoratee)
{
_decoratee = decoratee;
}
public List<Widget> Retrieve(List<long> ids) {
return ids
.Batch(10)
.AsParallel()
.SelectMany(b => _decoratee().Retrieve(b))
.ToList();
}
}
RetrieveTimer(装饰器)
class RetrieveTimer : IRetriever
{
private readonly IRetriever _retriever;
private const int timeout = 5;
public class RetrieveTimer(IRetriever retriever) : IRetriever
{
// This needs to be the "core" retriever
_retriever = retriever;
}
public List<Widget> Retrieve(List<long> ids) {
var task = Task.Run(() =>
{
return _retriever.Retrieve(ids);
}
);
if (task.Wait(TimeSpan.FromSeconds(timeout)))
{
return task.Result;
}
else
{
// handle "timer exceeded" fallout
throw new Exception("timer exceeded");
}
}
}
RetrieveCore
class RetrieveCore : IRetriever {
public List<Widget> Retrieve(List<long> ids)
{
// Do something
return new List<Widget>();
}
}
我正在努力注册,因为这不是一个简单的装饰器层次结构。相反,我们有:
- RetrieveBatcher(装饰器),它使用:
- RetrieveTimer(工厂),它本身就是以下的装饰器:
- RetrieveCore - 真正的猎犬
我们不得不 "cheat" 使用 SimpleInjector,按照:
// outermost layer:
container.Register<IRetriever, RetrieveBatcher>();
// Function (Factory) that returns "Timed" utility
// See: http://simpleinjector.readthedocs.io/en/latest/howto.html#register-factory-delegates
// This registers the Func<> as the singleton, not the RetrieveTimer instance
container.RegisterSingleton<Func<IRetriever>>(
() => new RetrieveTimer(new RetrieveCore()));
这可行,但实际的 "new RetrieveCore()" 依赖性似乎不太理想。
有没有什么方法可以配置 SimpleInjector 来正确处理这种情况?
我看不出为什么常规 RegisterDecorator
电话无法解决您的问题:
container.Register<IRetriever, RetrieveCore>();
container.RegisterDecorator<IRetriever, RetrieveTimer>();
container.RegisterDecorator<IRetriever, RetrieveBatcher>();
解析 IRetriever
后会产生以下对象图:
new RetrieveBatcher(() => new RetrieveTimer(new RetrieveCore()));
我们有一个由 3 个 decoratee 组成的层次结构,实现了如下接口:
public interface IRetrieve
{
List<Widget> Retrieve(List<long> ids);
}
我们正在尝试使用以下模式:
- RetrieveBatcher : IRetriever // 将调用批量化为更小的尺寸
- RetrieveTimer : IRetriever // 确保检索在一个时间间隔后超时
- RetrieveCore : IRetriever // 执行实际的检索
运行时代码如下所示:
RetrieveBatcher(装饰器)
class RetrieveBatcher : IRetriever
{
Func<IRetriever> _decoratee;
public RetrieveBatcher(Func<IRetriever> decoratee)
{
_decoratee = decoratee;
}
public List<Widget> Retrieve(List<long> ids) {
return ids
.Batch(10)
.AsParallel()
.SelectMany(b => _decoratee().Retrieve(b))
.ToList();
}
}
RetrieveTimer(装饰器)
class RetrieveTimer : IRetriever
{
private readonly IRetriever _retriever;
private const int timeout = 5;
public class RetrieveTimer(IRetriever retriever) : IRetriever
{
// This needs to be the "core" retriever
_retriever = retriever;
}
public List<Widget> Retrieve(List<long> ids) {
var task = Task.Run(() =>
{
return _retriever.Retrieve(ids);
}
);
if (task.Wait(TimeSpan.FromSeconds(timeout)))
{
return task.Result;
}
else
{
// handle "timer exceeded" fallout
throw new Exception("timer exceeded");
}
}
}
RetrieveCore
class RetrieveCore : IRetriever {
public List<Widget> Retrieve(List<long> ids)
{
// Do something
return new List<Widget>();
}
}
我正在努力注册,因为这不是一个简单的装饰器层次结构。相反,我们有:
- RetrieveBatcher(装饰器),它使用:
- RetrieveTimer(工厂),它本身就是以下的装饰器:
- RetrieveCore - 真正的猎犬
我们不得不 "cheat" 使用 SimpleInjector,按照:
// outermost layer:
container.Register<IRetriever, RetrieveBatcher>();
// Function (Factory) that returns "Timed" utility
// See: http://simpleinjector.readthedocs.io/en/latest/howto.html#register-factory-delegates
// This registers the Func<> as the singleton, not the RetrieveTimer instance
container.RegisterSingleton<Func<IRetriever>>(
() => new RetrieveTimer(new RetrieveCore()));
这可行,但实际的 "new RetrieveCore()" 依赖性似乎不太理想。
有没有什么方法可以配置 SimpleInjector 来正确处理这种情况?
我看不出为什么常规 RegisterDecorator
电话无法解决您的问题:
container.Register<IRetriever, RetrieveCore>();
container.RegisterDecorator<IRetriever, RetrieveTimer>();
container.RegisterDecorator<IRetriever, RetrieveBatcher>();
解析 IRetriever
后会产生以下对象图:
new RetrieveBatcher(() => new RetrieveTimer(new RetrieveCore()));