DryIoc 在实例解析之前调用异步初始化方法

huangapple go评论65阅读模式
英文:

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&lt;A&gt; 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&lt;Func&lt;A, Task&gt;&gt; parameter instead to postpone the whole initialization until the using method call.
    public A(Func&lt;A, Task&gt; initAsync) =&gt; _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&lt;A&gt;();
container.RegisterDelegate&lt;Func&lt;A, Task&gt;&gt;(_ =&gt; a =&gt; A.Initialization(a));

var a = container.Resolve&lt;A&gt;();
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&lt;A&gt;();

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.

huangapple
  • 本文由 发表于 2023年7月17日 20:45:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定