2012-05-22 10 views
5

Lassen Sie uns sagen, dass ich eine Schnittstelle haben, wie folgt aus:Mit Erweiterungsmethoden innerhalb erweiterten Klasse selbst

public interface ILoggable 
{ 
    void Log(Func<string> message, Logger.Type type); 
} 

Und einige Erweiterungsmethoden, wie folgt aus:

public static class Logger 
{ 
    public static void Log(this ILoggable loggable, Func<string> message) { loggable.Log(message, Type.Information); } 
    public static void Log(this ILoggable loggable, string prefix, byte[] data, int len) { /* snip */ } 
    public static void Log(this ILoggable loggable, Exception ex) { /* snip */ } 
    // And so on... 
} 

dann in jedem class CoreService : ServiceBase, ILoggable oder so, die ich umsetzen dass public void Log(Func<string> message, Logger.Type type) zu was auch immer ich mag (öffentliche Modifikator wird Art von meh ...) und verwenden Sie alle Erweiterungsmethoden, um tatsächliche Protokollierung zu tun.

So weit so gut ... oder nicht so gut? Stimmt etwas nicht mit diesem Ansatz? Wenn nicht, dann, warum die Unannehmlichkeiten:

catch (Exception ex) { 
    this.Log(ex); // this works 
    Log(ex); // this goes not 
+0

Sie können auch 'Log (this, ex)' aufrufen, was in dieser Situation insgesamt besser lesbar erscheint. –

+0

@HenkHolterman: Nun, Sie müssten Logger.Log (this, ex) aufrufen ... –

Antwort

3

Es scheint wie eine vernünftige Annäherung an mich selbst - aber die Forderung ausdrücklich this zu erklären, ist nur ein Teil davon, wie die Sprache arbeitet rund um Methoden der Erweiterung. Ich vermute, dass dies Aspekte der Sprachspezifikation sauberer macht, und diese Anforderung ist ausreichend selten (und die Umgehung ausreichend einfach), dass es besser war, mit der aktuellen Lösung zu gehen, als Dinge komplizierter zu machen, nur um fünf Zeichen in einem zu vermeiden relativ seltenes Szenario.

Membersuche für einfache Namen (Abschnitt 7.6.2 der C# 4 spec) ist kompliziert genug, ohne es noch schlimmer. Vergessen Sie nicht, dass sich der einfache Name sowohl auf einen Typ oder einen Typparameter als auch auf eine Methode beziehen kann. Da ist schon viel los.

Wenn ich zur Arbeit komme, überprüfe ich, ob es Anmerkungen zu Abschnitt 7.6.5.2 (Aufruf der Erweiterungsmethode) gibt, die "Insider-Informationen" darüber geben.


Bei näherer Betrachtung ist es etwas seltsam für die Entität scheint die Protokollierung zu auch wollen tut andere Dinge protokollieren - die einzige Art von Ausnahme erwarten würde ich es wäre, um zu sehen, wenn die Die Protokollierung schlägt fehl. In diesem Fall würde auch die Protokollierung der Ausnahme fehlschlagen.

+0

CoreService holt sich meist Daten über das Netzwerk und legt sie in die Datenbank. Es muss einige Mittel haben, um seine Aktivität zu protokollieren. Wenn einige seiner Operationen fehlschlagen, wird dies protokolliert. Wenn die Protokollierung fehlschlägt, wird sie möglicherweise ignoriert (für die Netzwerkprotokollierung) oder heruntergefahren (für die Dateiprotokollierung) oder watever - dies wird beim Implementieren der Schnittstelle implementiert. –

+0

@EugeneRyabtsev: Es fühlt sich so an, als müsste es ein Logging-Mitglied haben, das weiß, wie man loggen kann, anstatt selbst eine Logging-Schnittstelle zu implementieren. Es ist ein Implementierungsdetail - nicht etwas, das als eine Fähigkeit beworben werden sollte, die andere nutzen können, wozu Interfaces dienen. Trennen Sie die Bedenken der Protokollierung von "Daten über das Netzwerk erhalten". Schreiben Sie eine Klasse, deren * sole * -Auftrag protokolliert wird, und stellen Sie CoreService dann eine Instanz dieser Klasse zur Verfügung. –

+0

Dann muss dieses Mitglied, das als logger.Log (...) aufgerufen werden kann, eine polymorphe Klasse sein, um den ganzen Log (...) Code wiederzuverwenden, und ich muss für jeden speziellen Fall, zu dem ich mich anmelden möchte, einen Nachkommen erstellen wie man ein/aus filtert (oder es ziemlich groß und generisch an erster Stelle macht). Möglich natürlich. Zuvor habe ich etwas wie die mehrfache Vererbung in C++ implementiert, so dass eine Klasse ihre Aktivität implementieren und protokollieren kann und so ziemlich in sich abgeschlossen sein kann. Denkschnittstellen sind so nah wie es geht. –

Verwandte Themen