I have a class that is responsible of storing a bunch of async Funcs to execute them later. The signature of each Func differs only on the Task type. Here is the class:
public class FuncStore<TParameters> {
private readonly Dictionary<string, object> _funcCache = new();
public void AddFunc<T>(string key, Func<TParameters, Task<T>> value) {
_funcCache.Add(key, value);
}
public async Task ExecuteAllAsync(TParameters parameters) {
foreach(var (_, func) in _funcCache) {
// Problem here. How do I invoke each lambda?
}
}
}
Here is the parameters class for context:
public class DefaultParameters {
public string SomeProperty { get; set; }
}
And here is an example of use:
var store = new FuncStore<DefaultParameters>();
var lambda01 = (DefaultParameters parameters) => {
var str = parameters.SomeProperty + "01"; // Whatever
return Task<string>.FromResult(str); // Simulate async op
};
var lambda02 = (DefaultParameters parameters) => {
var number = Convert.ToInt32(parameters.SomeProperty) + 2; // Whatever
return Task<int>.FromResult(number); // Simulate async op
};
// These both lambdas differ on their return type
// one is Task<string> and the other is Task<int>
store.AddFunc("01", lambda01);
store.AddFunc("02", lambda02);
// Many other lambdas and additions later...
var parameters = new DefaultParameters();
await store.ExecuteAllAsync(parameters);
The problem is that I don't know how to invoke those lambdas. Here are my attempts so far:
public async Task ExecuteAllAsync(TParameters parameters) {
foreach(var (_, func) in _funcCache) {
// Problem here. How do I invoke each lambda?
// Attempt 1:
var typedFunc = func as Func<TParameters, Task<object>>; // NullReferenceExeption, the cast fails
await typedFunc(parameters);
// Attempt 2 (almost):
var asDelegate = func as Delegate;
// I manage to get the task...
var task = (Task)asDelegate.DynamicInvoke(new object[]{ parameters });
// ... but if I await it, I get a compile error: "Argument 1: cannot convert from 'void' to 'bool'"
Console.WriteLine(await task);
}
await Task<int>.FromResult(0); // Just to make the compiler happy while I debug
}
Here is the .NET Fiddle.
Any ideas? Thanks in advance.
One way is to use dynamic
, in both the function cache and the delegates:
var lambda01 = (DefaultParameters parameters) => {
var str = parameters.SomeProperty + "01"; // Whatever
return Task.FromResult<dynamic>(str); // Simulate async op
};
and:
private readonly Dictionary<string, dynamic> _funcCache = new();
public void AddFunc(string key, Func<TParameters, Task<dynamic>> value) {
_funcCache.Add(key, value);
}
Working example: https://dotnetfiddle.net/rTm8ZM