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();
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();
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);
I am very interested on any ideas for this topic as well as for the alternative solutions.