Autofac:注册异步工厂方法 [英] Autofac: Registering an Async Factory method
问题描述
TL; DR:Autofac是否支持类似AutoFixture的fixture.Get()
机制?
TL;DR: Does Autofac support something like AutoFixture's fixture.Get()
mechanism ?
我正在使用Autofac,需要调用如下所示的异步工厂方法:
I'm using Autofac and need to invoke async factory methods which look like this:
class AppModel
{
public static async Task<AppModel> CreateAsync(IDependency x, IDependency2 y)
{ ... }
}
执行这样的方法并由Autofac提供参数的最简单方法是什么?即,我希望能够执行以下操作:
What is the simplest way for me to execute such a method and have the arguments be supplied by Autofac? i.e., I want to be able to do something like:
Task<AppModel> creationTask = <some autofaccery>(AppModel.CreateAsync);
var appModel = await creationTask();
其中,<some autofaccery>
表示与ContainerBuilder
和/或IContainer
进行交互的某种机制和/或某种形式的
where <some autofaccery>
represents some mechanism of interacting with ContainerBuilder
and/or IContainer
and/or some form of generated Delegates or similar which is succinct in nature and isolates me from specifying the arguments to the Factory Method explicitly. i.e., I want to avoid having to explicitly resolve each argument [and/or have to update them as the dependencies change] like I do atm:
var appModel = await AppModel.CreateAsync(
container.Resolve<IDependency>(),
container.Resolve<IDependency2>());
我在基础设施组件区域内,靠近合成根",可以潜在地以编程方式定义组件注册和/或做其他仅局限于此的事情.我不介意反射被涉及,因为它仅被调用一次.
I am in infrastructure components territory, close to the Composition Root and could potentially programmatically define Component Registrations and/or do other nastiness that should be confined to there. I don't mind reflection being involved as it's only being invoked once.
关键是我确实需要观察来自Task
的任何Exception
.
What is critical is that I do need any Exception
s emanating from the Task
to be observed.
Task<T>
在很大程度上是一条红色鲱鱼,但要点是,遵循定义同步工厂方法并通过Autofac正常工作的正常模式不会成功(至少不是直接实现),即不能只是将其更改为:
The Task<T>
is a red herring to a large degree, but the point is that following the normal pattern of defining a synchronous factory method and having Autofac work through that won't fly (at least not directly), i.e. I can't just change it to:
public static AppModel CreateAsync(IDependency x, IDependency2 y)
{ ... }
我还想避免两阶段初始化-在对象初始化之前,我不需要对象.
I'd also like to avoid two-phase initialization - I don't need the object to be available until it's been initialized.
推荐答案
滥用 LazyTask<T>
,可以转换一个CreateAsync
方法转换为Autofac 可以解决的问题:-一种类型[源自LazyTask<T>
],看起来像这样:
Abusing LazyTask<T>
, one can transform a CreateAsync
method into something Autofac can resolve :- a Type [derived from LazyTask<T>
], which looks like so:
class AppModel
{
public class AsyncFactory : LazyTask<AppModel>
{
public AsyncFactory(IDependency x, IDependency2 y) : base(async() =>
new AppModel( x.CalculateA(await y.CalculateB())))
{}
}
private AppModel(A a) { ... }
}
这可以消耗如下:-
var appModel = await container.Resolve<AppModel.AsyncFactory>();
不接受这一点,因为我仍然觉得这有一个更清晰的机会-即,如果Autofac对Task<T> CreateAsync
方法编写如下特殊处理:-
Not accepting this as I still feel there is an opportunity for this to be clearer - i.e. if Autofac was to apply a special treatment to Task<T> CreateAsync
methods written as follows:-
class AppModel
{
public async Task<AppModel> CreateAsync(IDependency x, IDependency2 y) =>
new AppModel( x.CalculateA(await y.CalculateB()));
}
自动将它们注册为类型Task<T>
,允许一个人在不依赖我的Task
包装器类型的情况下进行以下消费:-
automatically registering them as the type Task<T>
, allowing one to consume as follows without relying on my Task
wrapper type:-
var appModel = await container.Resolve<Task<AppModel>>();
这篇关于Autofac:注册异步工厂方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!