Ich arbeite mit einer c # -Klasse von Drittanbietern, die viele großartige Methoden und Eigenschaften hat - aber im Laufe der Zeit muss ich diese Klasse um eigene Methoden und Eigenschaften erweitern. Wenn es mein Code wäre, würde ich einfach diese Klasse als meine Basisklasse verwenden und oben meine eigenen Eigenschaften und Methoden hinzufügen - aber diese Klasse hat einen internen Konstruktor. (Meiner Meinung nach war es kurz, um den Konstruktor an erster Stelle intern zu machen - warum sollte man die Fähigkeit zur Unterklasse einschränken?)
Das einzige, woran ich denken konnte, war, Methoden / Eigenschaften für meine Klasse zu erstellen, die einfach in ihre Klasse eintraten - aber es ist viel Code und, nun, es fühlt sich einfach nicht richtig an.
Gibt es eine Möglichkeit, diese Klasse eine Basisklasse zu verwenden?
Ich werde nicht diskutieren, ob Sie Ihre eigene Fassade um diese 3rd-Party-Klasse bauen können. Frühere Autoren haben Recht, die Bibliothek könnte so gestaltet sein, dass dies nicht möglich ist. Angenommen, sie haben einige gekoppelte Klassen, die Singletons haben, die in einer bestimmten Reihenfolge oder in ähnlicher Weise initialisiert werden sollten - es kann viele Designfehler (oder Features) geben, die Entwickler von Drittanbietern nie interessieren, weil sie nicht davon ausgehen, dass Sie sie verwenden ihre Bibliothek auf diese Weise.
Aber OK, nehmen wir an, dass das Erstellen einer Fassade keine unmögliche Aufgabe ist und Sie tatsächlich nur ein Problem haben - es gibt zu viele Methoden, um Wrapper herum zu schreiben und das ist es nicht gut, dies manuell zu tun.
Ich sehe 3 Lösungen, um genau dieses Problem anzugehen
1) Ich nehme an, dass neue "dynamische" .NET 4.0-Typen es Ihnen ermöglichen, dieses Problem zu umgehen, ohne "Acres Code" schreiben zu müssen. Sie sollten eine Instanz einer Drittanbieterklasse als privates Mitglied mit dynamischem Schlüsselwort in Ihre Klasse aufnehmen Ihre Klasse sollte von Dynamic abgeleitet sein oder die IDynamicObject-Schnittstelle implementieren. Sie müssen GetMember / SetMember Funktionen implementieren, die alle Aufrufe an die gekapselte Instanz der 3rd-Party-Klasse
weiterleitenNun, c # 4.0 ist eine Zukunft. Sehen wir uns andere Lösungen an:
2) Schreiben Sie keinen Code manuell, wenn Sie eine beträchtliche Anzahl an öffentlichen Methoden haben (sagen Sie mehr als 100). Ich würde eine kleine Konsole-App schreiben, die Reflexion verwendet und alle öffentlichen Mitglieder findet und dann automatisch Code zum Aufrufen der gekapselten Instanz generiert. Zum Beispiel
%Vor%3) Sie können das gleiche wie 2, aber mit Hilfe der vorhandenen Reflektionswerkzeuge, zum Beispiel RedGate .NET Reflector. Es wird Ihnen helfen, alle Klassen- und Methoden-Signaturen aufzulisten. Dann fügen Sie all das in Word ein und ein einfaches VB-Makro lässt Sie den gleichen Code wie in 2 erzeugen. Anmerkung: Sobald Sie den Code nicht kopieren, sondern nur Signaturen der Kopiermethode, die öffentlich verfügbar sind, glaube ich nicht, dass Sie gegen die Lizenzvereinbarung verstoßen, aber es lohnt sich trotzdem, erneut zu prüfen
Sie fragen: "Warum die Fähigkeit zur Unterklasse einschränken?"
Der Entwurf für die Vererbung ist schwierig, insbesondere wenn Sie andere Entwickler so entwickeln, dass sie von Ihrer Klasse erben. Wie Josh Bloch in Effective Java sagt, sollten Sie die Vererbung entwerfen oder verbieten. Meiner Ansicht nach sollten Sie, solange Sie keinen guten Grund haben, eine Vererbung zu entwerfen, dies nicht spekulativ tun.
Implementiert die Klasse eine Schnittstelle, die Sie auch implementieren könnten (möglicherweise indem Sie die meisten Aufrufe an eine Instanz des Originals weiterleiten)? Es gibt oft keine wirklich elegante Antwort hier - und die beste Lösung hängt von der genauen Situation ab, einschließlich was Sie der Klasse hinzufügen möchten.
Wenn Sie keine weiteren State - nur Bequemlichkeit Methoden, effektiv hinzufügen - dann können Erweiterung Methoden gut für Sie arbeiten. Sie ändern jedoch nicht, welche Daten ein Objekt speichern kann. Wenn Sie also Ihre eigenen spezialisierten Daten hinzufügen müssen, funktioniert das nicht.
Nur wenn Ihre Klasse in derselben Assembly wie die Klasse lebt, von der Sie erben möchten. Ein interner Konstruktor begrenzt die konkreten Implementierungen der abstrakten Klasse auf die Assembly, die die Klasse definiert. Eine Klasse, die einen internen Konstruktor enthält, kann nicht außerhalb der Assembly instanziiert werden.
Klingt wie eine perfekte Anwendung für Erweiterungsmethoden:
"Erweiterungsmethoden ermöglichen das Hinzufügen von Methoden zu vorhandenen Typen, ohne einen neuen abgeleiteten Typ zu erstellen, den Originaltyp neu zu kompilieren oder auf andere Weise zu modifizieren. Erweiterungsmethoden sind eine besondere Art von statischen Methoden, aber sie werden so aufgerufen, als ob sie sie wären Instanzmethoden für den erweiterten Typ Für Client-Code, der in C # und Visual Basic geschrieben wurde, gibt es keinen offensichtlichen Unterschied zwischen dem Aufruf einer Erweiterungsmethode und den Methoden, die tatsächlich in einem Typ definiert sind. "
Wenn die Klasse einen internen Konstruktor hat und es keine öffentlichen Konstruktoren gibt, deutet das darauf hin, dass die Designer nicht beabsichtigt haben, dass sie unterklassifiziert werden. In diesem Fall können Sie die Kapselung verwenden oder Sie können Erweiterungsmethoden verwenden.
Tags und Links c# constructor design-patterns design