Reputation: 5499
My goal is to pass any function with a return type to my Execute method and serialize and store its results. Below is a rough idea of what I am trying to do, obviously won't compile but hopefully it gets the idea across. I suppose I should also be able to handle nested Tasks recursively. Thoughts?
public static TResult Execute<TResult>(Func<TResult> method)
where TResult : class
{
var result = method();
if(result is Task)
{
var taskResult = await result;
StoreResult(taskResult);
}
else
{
StoreResult(result);
}
}
Upvotes: 2
Views: 262
Reputation: 244757
I agree with Lee's comment that having a separate overload for Func<Task<TResult>>
is the right solution.
But if you really want to do this using one overload, you could use reflection and dynamic
to make this work:
public async static Task Execute<TResult>(Func<TResult> method) where TResult : class
{
var result = method();
if (typeof(TResult).IsGenericType
&& typeof(TResult).GetGenericTypeDefinition() == typeof(Task<>))
{
var taskResult = await (dynamic)result;
StoreResult(taskResult);
}
else
{
StoreResult(result);
}
}
Upvotes: 1
Reputation: 54359
Here's a contrived example that shows how it can be done.
I'd question the wisdom of this pattern. I'd prefer to always return a task, even if a task isn't always needed. The overhead of Task.FromResult()
is usually negligible.
public async Task<T> Foo<T>()
{
var mightBeATask = Bar<T>();
var task = mightBeATask as Task<T>;
if( task != null )
{
return await task;
}
return (T)mightBeATask;
}
private object Bar<T>()
{
return Task.FromResult( default( T ) );
}
Upvotes: 2