2016-09-29 5 views
3

プロジェクト全体に散らばっている非常に醜いコードがあります。このコードの唯一の違いは、異なるメソッドが呼び出される1行です。呼び出されるメソッドは常にboolを返します。関数をパラメータとして渡すことができる一般的なC#関数を構築する

これをリファクタリングして独自のメソッドに抽出し、このメソッドに(可能であれば)1ライナーを渡したいと思っています。これを行うにはFunc<>を使用します。

ここに私がやろうとしていることがあります。私は、彼らが唯一のFuncs<>通過を示して発見した例から、正しい軌道に乗っています、レポ

public async Task<bool> IsCustomerComplete(int id) 
{ 
    ...removed other code here 
    return true; 
} 

このメイクセンスをいから

public async Task<bool> SomeMethod() 
{ 
    //code removed for readability. 

    //IsCustomerComplete will return a bool 
    var process = await RepeatableMasterPiece(1, 2, _myRepo.IsCustomerComplete(someParameterRequired)); 

    //do something with process result 
    return process; 
} 

private async Task<bool> RepeatableMasterPiece(int param1, int param2, Func<Task<bool>> method) 
{ 
    int retry = 0; 
    bool soapComplete = false; 
    string soapFault = "just a placeholder for example"; 
    bool blackListStatus = false; 
    while (!soapComplete && retry <= 1) 
    { 
     try 
     { 
      if (soapFault != null) 
      { 
       //do some stuff with param1 & param2 here 
      } 
      if (!soapComplete) 
      { 
       return await method.Invoke(); 
      } 
     } 
     catch (FaultException ex) 
     { 
      soapFault = ex.Message; 
      retry++; 
      if (retry > 1) 
      { 
       throw ex; 
      } 
     } 
    } 
} 

できるだけ明確なものを維持しようとしましたstringまたはintのように表示されます。

+1

'_myRepo.IsCustomerComplete'は何を返しますか? – Nkosi

+0

boolを返します。私がこの関数に渡したいすべてのメソッドは常にboolを返します –

+0

そして、そのメソッドを非同期で実行したいですか?あなたの例は、現在提供されている情報に基づいてコンパイルされないからです。 – Nkosi

答えて

1

ここに提供された詳細に基づいた例です。

public async Task SomeMethod() { 
    //code in method. 

    var _myRepo = new repo(); 
    var someParameterRequired = 1; 
    var process = await RepeatableMasterPiece(1, 2,() => _myRepo.IsCustomerComplete(someParameterRequired)); 

    //do something with process result 
} 

private async Task<bool> RepeatableMasterPiece(int param1, int param2, Func<Task<bool>> method) { 
    int retry = 0; 
    bool soapComplete = false; 
    string soapFault = "just a placeholder for example"; 
    bool blackListStatus = false; 
    while (!soapComplete && retry <= 1) { 
     try { 
      if (soapFault != null) { 
       //do some stuff with param1 & param2 here 
      } 
      if (!soapComplete && method != null) { 
       return await method(); 
      } 
     } catch (FaultException ex) { 
      soapFault = ex.Message; 
      retry++; 
      if (retry > 1) { 
       throw ex; 
      } 
     } 
    } 
    return false; 
} 

ここでの仮定は、すべてのターゲットメソッドがターゲット関数がパラメータを必要としない場合は、他の答えで述べたように、あなたが行うことができますし、ちょうどなし機能自体を提供Task<bool>

を返すことになるということです括弧。

+0

両方のおかげで@再帰的にあなたの助けを感謝しました –

0

私はチェックアウトAction<T>Func<T, TResult>の代議員です。

  • void匿名メソッドを渡す場合は、Action<T>代理人を使用してください。

  • 戻り値の型を持つ匿名メソッドを渡す必要がある場合は、Func<TResult>デリゲートを使用します。

MSDNにはいくつかの良い例があります:私は私のキャリアの上にアクションと機能を何度も

Func Delegates MSDN

Action Delegates MSDN

を使用していました。リファクタリングできない密接に結合されたコードに機能を追加すると便利です。

ただし、疎結合コードを記述するときは、その正しい使い方を使用する必要があります。実装者に独自の機能を提供するオプションを提供したいときが何度もあります。

3

私はあなたの目標を理解すれば、あなたはとても近くにいる。欠けている最大の問題は、メソッドをFunc<>デリゲートに変換することです。あなたの質問では、あなたは引数のカッコを含めました。メソッドを呼び出さない場合は、これらは必要ありません。

だから、基本的にこれはあなたが望むものです。

var process = await RepeatableMasterPiece(1, 2, _myRepo.IsCustomerComplete); 
+0

これもコンパイルされません。 OPは 'Func >'を期待しています。私はまだOPの予想される動作を明確にしようとしています。 – Nkosi

+0

私は 'async'を想定しています。これがこのように定義されていれば、うまくいくでしょう。 – recursive

+0

私は同じことを考えましたが、Opは 'bool IsCustomerComplete() 'と答えました – Nkosi

関連する問題