英文:
DryIoc Call async initialization method before instance resolve
问题
我有一个A类。它必须是一个singleton
,并且在创建时必须调用async Initialization
方法。我在DryIoc
文档中没有找到合适的功能。我觉得RegisterDelegate
方法是最接近的,但它不接受异步的lambda作为参数。
为了清楚起见,我将提供一个示例以供参考:
public class A
{
...
public async Task<A> Initialization() {...}
...
}
var instance = await new A().Initialization();
英文:
I have a class A. It must be a singleton
and the async Initialization
method must be called when it is created. I did not find suitable functionality in the DryIoc
documentation. It seems to me that the RegisterDelegate
method is the closest, but it does not take an asynchronous lambda as a parameter.
For clarity, I will give an example to be in front of your eyes:
public class A
{
...
public async Task<A> Initialization() {...}
...
}
var instance = await new A().Initialization();
答案1
得分: 2
答案 1:
async
初始化目前还不受 DryIoc 支持,因为存在 双色函数问题 及其相关复杂性。
基本上,我需要引入一个独立的 await
调用图,用于整个依赖链,其中一些依赖从 ResolveAsync
或类似的 API 开始是 async
。
在没有它的情况下,您可以使用在文章末尾讨论的方法:https://endjin.com/blog/2023/01/dotnet-csharp-lazy-async-initialization。
在这种方法中,您将等待初始化的部分从构建阶段移到方法中。
因此,您可以将 async 初始化作为构造函数的 Func 依赖项添加:
public class A
{
readonly Task _finishInitAsync;
// 实际上,在构造函数中启动初始化部分以启动作业,但将已完成或正在进行的初始化的等待延迟到第一个使用方法。
// 或者,您可以使用 Lazy<Func<A, Task>> 参数来延迟整个初始化,直到使用方法调用。
public A(Func<A, Task> initAsync) => _finishInitAsync = initAsync(this);
// 将其设为静态以脱离 A 并简化传递
public static async Task Initialization(A a) {...}
...
public async Task MethodUsingTheInit()
{
await _finishInitAsync();
// 做一些事情
}
}
container.Register<A>();
container.RegisterDelegate<Func<A, Task>>(_ => a => A.Initialization(a));
var a = container.Resolve<A>();
await a.MethodUsingTheInit();
答案 2:
您可以进入全手动模式,这对我来说似乎更简单。
在第一次使用之前手动调用 Initialization
。
// `New` 允许从容器中注入其依赖项来构造 A,但实际上不会注册 A 本身。
var a = container.New<A>();
await A.Initialization(a);
// 然后将完全初始化的 A 注册到容器中
container.RegisteInstance(a);
反馈:
我对这个主题以及替代解决方案的任何想法都非常感兴趣。
英文:
Answer 1
The async
initialization is not yet supported by the DryIoc because of the two-colored function problem and the associated complexity.
Basically, I need to introduce the separate await
call graph generated for the whole chain of dependencies where some of them are async
starting from the ResolveAsync
or similar API.
In the absence of it, you may use the approach discussed at the end of the article https://endjin.com/blog/2023/01/dotnet-csharp-lazy-async-initialization.
In this approach, you are moving the await part of the initialization outside the construction phase into the method(s).
So you may add the async Initialization as a Func dependency into the constructor:
public class A
{
readonly Task _finishInitAsync;
// Actually kicking off the initialization part in the constructor to start the job,
// but postpone the await of the already finished or in-progress initialization until the first using method.
// Alternatively, you may use Lazy<Func<A, Task>> parameter instead to postpone the whole initialization until the using method call.
public A(Func<A, Task> initAsync) => _finishInitAsync = initAsync(this);
// Making it static to detach from the A and simplify the passing it around
public static async Task Initialization(A a) {...}
...
public async Task MethodUsingTheInit()
{
await _finishInitAsync();
// do stuff
}
}
container.Register<A>();
container.RegisterDelegate<Func<A, Task>>(_ => a => A.Initialization(a));
var a = container.Resolve<A>();
await a.MethodUsingTheInit();
Answer 2
You may go full manual mode, which appears much simpler to me.
Call the Initialization
manually before the first use.
// `New` allows to construct the A by injecting its dependencies from the container,
// but without actually registering the A itself.
var a = container.New<A>();
await A.Initialization(a);
// Then register the fully initialized A into container
container.RegisteInstance(a);
Feedback
I am very interested on any ideas for this topic as well as for the alternative solutions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论