2010-12-16 4 views
2

問題のコードはロボット(CodeSmith)によって書かれており、維持するのは苦痛です。それはクライアント側のWCFのプロキシコードだと、すべてのこれらの行があるすべてのサービスメソッドのために繰り返され、あなたが推測できるとおりメソッド呼び出しの共通機能を追加するにはどうすればよいですか?

public AddressProgramTemplate GetById(System.Int32 _id) { 
    try { 
     return Service.GetById(_id); 
    } catch (FaultException<ErrorInfo> ex) { 
     throw new ProxyServerBusinessException(ex.Detail); 
    } catch (FaultException) { 
     throw new ProxyServerBusinessException(null); 
    } catch (EndpointNotFoundException ex) { 
     throw new ProxyServerTechnicalException<EndpointNotFoundException>(ex); 
    } catch (CommunicationObjectFaultedException ex) { 
     throw new ProxyServerTechnicalException<CommunicationObjectFaultedException>(ex); 
    } catch (CommunicationException ex) { 
     throw new ProxyServerTechnicalException<CommunicationException>(ex); 
    } catch (ObjectDisposedException ex) { 
     throw new ProxyServerTechnicalException<ObjectDisposedException>(ex); 
    } catch (TimeoutException ex) { 
     throw new ProxyServerTechnicalException<TimeoutException>(ex); 
    } 
} 

(その多くがあります):これは、と少し似ています。ロボットにとっては、私にとっては悲しみなので、私はそれをリファクタリングし始めました。まず、例外ロジックや取り扱いには、Microsoftエンタープライズライブラリに委任されており、共通のコードは、基本クラスに移行:

public TResult WrapServiceMethod<TResult>(Func<TResult> serviceMethod) { 
    TResult result = default(TResult); 
    try { 
     result = serviceMethod(); 
    } catch (Exception ex) { 
     bool rethrow = ExceptionManager.HandleException(ex, ExceptionPolicyNames.ClientRequestPolicy); 
     if (rethrow) throw; 
    } 
    return result; 
} 

をこれまでのところは良い、醜いのtry/catchパイルは、きちんとしたワンライナー次のようになります。

return WrapServiceMethod<AddressProgramTemplate>(() => Service.GetById(_id)); 

少しの努力と無効な方法も同様にカバーされます。 「匿名メソッド、ラムダ式、またはクエリ式内refまたはパラメーター 『endDateに』外には使用できません」で

public void GetPeriod(AddressProgram program, out DateTime startDate, out DateTime endDate){ 
    WrapServiceMethod(() => Service.GetPeriod(program, out startDate, out endDate)); 
} 

結果と私はwhyを理解する:サービスコールがoutパラメータを使用するときに問題が来ます。私は理想的に持っていると思い何

)が(例えばながら、()または使用などのカスタムオペレータブロックを定義する機能ですので、私は「

wrapexception { ... } 

を書いて、その後ずっと幸せに暮らすが、私はドンができこのトリックは.NETで可能だと思います。 outパラメータを使用せずにすべてのサービスメソッドを書き直すことが最後の手段であると仮定して、他のオプションはありますか?

答えて

2

PostSharpなどのアスペクト指向プログラミングライブラリの後にいるような感じです。

あなたはこのような例外をキャッチするようなことを行うことができますを指定、ロギング、トレースの規則に基づいて、コンパイル後にILに挿入されている例外ハンドラを作成することができるなど

これの利点は、あなたが一度様相を書きです複数のメソッドに適用することができます。これらのメソッドは、例外処理などのクロスカッティングの問題が側面によって処理されるため、手元の特定のタスクとは無関係のコードで煩雑になることはありません。

例外を処理する方法を示すhttp://www.sharpcrafters.com/solutions/monitoring#exception-monitoringの例を見てください。

+0

有望に見える - そのロボットは、ソースコードの代わりにコンパイルされたアセンブリを変更します。確かに維持する方がずっと簡単です。重大なパフォーマンス上の欠点はありますか? –

+0

すべてのAOPライブラリがポストコンパイルではないことを指摘しておきます。 PostSharpはありますが、コンパイルされたアセンブリは変更されません。 dodgyの面を書かない限り、パフォーマンスに影響を与えるべきではありません。いつものように、プロフィールと比較して確かめてください。 Spring.NETは、プロキシオブジェクトを使用してAOPを実装する方法としてメソッドインターセプタを作成します。 –

+0

私はおそらくMicrosoft Enterprise LibraryからPolicyInjectionに行くのは、Microsoft(販売しやすい)であり、すでにプロジェクトで使用されている(販売しやすい)ためです。 –

1

あなたはこのような何か行うことができます(私はあなたが避けたいと確信しているので、すべての呼び出し元のコードを変更すること、)out署名を変更する代わりに:

public void GetPeriod(AddressProgram program, out DateTime startDate, out DateTime endDate) 
{ 
    var outs = WrapServiceMethod(() => 
     { 
      DateTime sd; 
      DateTime ed; 
      Service.GetPeriod(program, out sd, out ed)); 
      return new {sd, ed}; 
     } 
    startDate = outs.sd; 
    endDate = outs.ed; 
} 
+1

優秀なチップ、ありがとう!完全なAOP実装が緑色に点灯するまで、これを迅速に修正してください。 –

関連する問題