The code in question is written by robot (CodeSmith) and it is a pain to maintain. It looks somewhat similar to:
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);
}
}
As you can guess, it's a client-side WCF proxy code and all these lines are repeated for every service method there is (and there are many). What's good for robot is a sorrow for me, so I started to refactor it. First of all, the exception logic and handling is delegated to Microsoft Enterprise Library and common code migrated to base class:
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;
}
So far so good, the ugly try/catch pile becomes a neat one-liner:
return WrapServiceMethod<AddressProgramTemplate>(() => Service.GetById(_id));
A little effort and void methods covered as well. The problem comes when service calls use out
parameters:
public void GetPeriod(AddressProgram program, out DateTime startDate, out DateTime endDate){
WrapServiceMethod(() => Service.GetPeriod(program, out startDate, out endDate));
}
Results in "Cannot use ref or out parameter 'endDate' inside an anonymous method, lambda expression, or query expression" and I understand why.
What I would ideally like to have is an ability to define custom operator blocks such as while() or using(), so I could write
wrapexception { ... }
and live happily ever after, but I don't think this trick is possible with .NET. Assuming that rewriting all service methods without out
parameters is a last resort, do I have any other options?