I would to call an asynchronous function in an Unity injection factory, like so...
Container.RegisterType<HttpClient>(new InjectionFactory(
async c => await Create()));
... but it says...
Error CS4010: Cannot convert async lambda expression to delegate type 'Func'. An async lambda expression may return void, Task or Task, none of which are convertible to 'Func'.
Is there a way around this?
Register the factory as Task<HttpClient>
using the DelegateInjectionFactory
. Then you can await
it after it is injected, in code that you control.
public static IUnityContainer CompositionRoot()
{
var container = new Unity.UnityContainer();
container.RegisterType<Application>();
container.RegisterType<Task<HttpClient>>
(
new DelegateInjectionFactory
(
new Func<Task<HttpClient>>
(
async () => await Create()
)
)
);
return container;
}
public static async Task<HttpClient> Create()
{
await Task.Delay(1); //Simulate doing something asynchronous
return new HttpClient();
}
Example of a class that would receive the injection:
public class Example
{
protected readonly Task<HttpClient> _client; //Injected
public Example(Task<HttpClient> client)
{
_client = client;
}
public async Task<string> Run()
{
var result = await (await _client).GetAsync("http://www.StackOverflow.com");
var text = await result.Content.ReadAsStringAsync();
return text;
}
}
Now Create()
will be executed asynchronously, but is not awaited by the container (which isn't set up for that). Instead, it is awaited by your own code, in the class that consumes it, which you have control over.
Note: While this example demonstrates that it is possible, I would probably not do this in production code. It is more common to write a factory class, give it an async method, inject the factory class, and await the method in the class receiving the injection.