2016-11-10 3 views
2

私の目標は、戻り値の型を持つ関数をExecuteメソッドに渡し、その結果をシリアル化して保存することです。以下は、私がやろうとしていることの大まかなアイデアです。明らかにコンパイルされませんが、うまくいけばアイデアが得られます。私も入れ子になったタスクを再帰的に扱うことができるはずです。思考?メソッドがタスクを返すかどうかを判断し、それがあればそれを待つことはできますか?

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); 
     } 
    } 
+5

は、2つのオーバーロードを作成し、1 'のFunc <タスク>'となります他の 'Func '。 – Lee

答えて

1

私はFunc<Task<TResult>>ための別のオーバーロードを持つことが適切なソリューションであることを李氏のコメントに同意します。

しかし、あなたは本当にこの使用して1つのオーバーロードを行いたい場合は、この作品にするために反射してdynamicを使用することができます。

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); 
    } 
} 
+0

ありがとうございました!私は過負荷でそれをやろうと思っていますが、これはまさに私が探していたものです。 – Mike

2

これはどのようにして行うことができるかを示す例です。

私はこのパターンの知恵に疑問を持っています。タスクが常に必要なわけではない場合でも、私はいつもタスクを返すことを好みます。 Task.FromResult()のオーバーヘッドは通常ごくわずかです。

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)); 
} 
関連する問題