Der betreffende Code wird von Roboter (CodeSmith) geschrieben und es ist ein Schmerz zu pflegen. Es sieht ein wenig ähnlich:Wie kann ich allgemeine Funktionalität um Methodenaufrufe hinzufügen?
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);
}
}
Wie Sie sich vorstellen können, es ist eine clientseitige WCF-Proxy-Code und alle diese Linien werden für jeden Service-Methode wiederholt gibt es (und es gibt viele). Was für Roboter gut ist, ist ein Kummer für mich, also habe ich angefangen, es zu refaktorisieren. Zunächst einmal wird die Ausnahmelogik und die Handhabung zu Microsoft Enterprise Library übertragen und gemeinsamen Code Basisklasse migriert:
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 weit so gut, das hässliche try/catch Stapel wird ein ordentlich Einzeiler:
return WrapServiceMethod<AddressProgramTemplate>(() => Service.GetById(_id));
Ein wenig Aufwand und leere Methoden abgedeckt. Das Problem kommt, wenn Service-Anrufe out
Parameter verwenden:
public void GetPeriod(AddressProgram program, out DateTime startDate, out DateTime endDate){
WrapServiceMethod(() => Service.GetPeriod(program, out startDate, out endDate));
}
Ergebnisse in "nicht ref verwenden oder out-Parameter 'endDate' innerhalb einer anonymen Methode, Lambda-Ausdruck oder Abfrageausdruck" und ich verstehe why.
Was würde ich im Idealfall haben mag, ist eine Möglichkeit, benutzerdefinierte Operator Blöcke wie while() oder mit() zu definieren, so konnte ich
wrapexception { ... }
schreiben und glücklich leben, aber ich don‘ Ich denke, dieser Trick ist mit .NET möglich. Angenommen, dass das Umschreiben aller Service-Methoden ohne Parameter out
der letzte Ausweg ist, habe ich weitere Optionen?
sieht vielversprechend aus - ein Roboter, Ändert die kompilierte Assembly anstelle des Quellcodes. Sollte in der Tat viel einfacher zu pflegen sein. Gibt es ernsthafte Leistungsnachteile? –
Sollte darauf hinweisen, dass nicht alle AOP-Bibliotheken nach der Kompilierung sind. PostSharp ist, aber andere ändern die kompilierte Assembly nicht. Die Leistung sollte nicht beeinflusst werden, es sei denn, Sie schreiben einen zwielichtigen Aspekt. Wie immer, Profil und Vergleich sicher sein. Spring.NET verwendet Proxy-Objekte, um Methoden-Interzeptoren als ihren Weg zur Implementierung von AOP zu erstellen. –
Ich werde wahrscheinlich mit PolicyInjection von Microsoft Enterprise Library gehen, nur weil es Microsoft (einfach zu verkaufen) und es ist bereits in unserem Projekt (noch einfacher zu verkaufen). –