2009-06-17 6 views
8

Ich arbeite mit einer C# -Klasse von Drittanbietern, die viele tolle 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 meine eigenen Eigenschaften und Methoden oben hinzufügen - aber diese Klasse hat einen internen Konstruktor. (Meiner Meinung nach war es kurz, um den Konstruktor intern zu machen - warum sollte man die Unterklasse einschränken?)Gibt es eine Möglichkeit, von einer Klasse mit einem internen Konstruktor abzuleiten?

Das einzige, was mir einfiel, war, Methoden/Eigenschaften für meine Klasse zu erstellen, die einfach aufgerufen wurde ihre - aber es ist Hektar Code und, naja, es fühlt sich einfach nicht richtig an.

Gibt es eine Möglichkeit, diese Klasse eine Basisklasse zu verwenden?

+1

Teil eins: http://blogs.msdn.com/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx –

+1

Teil zwei: http: //blogs.msdn .com/ericlippert/archive/2008/10/06/prevent-third-party-derivation-part-two.aspx –

Antwort

0

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 haben tatsächlich nur ein Problem - gibt es zu viele Methoden, die Sie Wrapper um schreiben müssen, und es ist nicht gut, dies zu tun manuell.

Ich sehe drei Lösungen genau das Problem

1) zu adressieren Ich nehme an, dass neue „dynamische“ Arten von .NET 4.0 ermöglicht es Ihnen, dieses Problem zu umgehen, ohne „Morgen-Code“ schreiben Sie sollten verkapseln Sie eine Instanz der 3rd-Party-Klasse als privates Mitglied mit dem dynamischen Schlüsselwort in Ihre Klasse. Ihre Klasse sollte von Dynamic abgeleitet sein oder die IDynamicObject-Schnittstelle implementieren. Sie haben GetMember/setMember Funktionen zu implementieren, die alle Anrufe auf die verkapselte Instanz von 3rd-Party-Klasse

Well weiterleiten, c 4.0 # eine Zukunft ist, wir uns auf andere Lösungen finden Sie unter:

2) Schreiben Sie nicht Code manuell, wenn Sie eine erhebliche 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

public type MethodName(params) 
{ 
    this.anInstanceOf3rdPartyClass.MethodName(params); 
} 

3) Sie können das gleiche tun wie 2, aber mit Hilfe der bestehenden Reflexions Tool, 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 generieren wie in 2. Anmerkung: Sobald Sie nicht den Code kopieren, sondern nur Signaturen der Kopiermethode, die öffentlich verfügbar sind Ich glaube nicht, dass Sie gegen die Lizenzvereinbarung verstoßen, aber es lohnt sich, es erneut zu überprüfen

2

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.

2

Klingt wie eine perfekte Anwendung für Erweiterungsmethoden:

MSDN extension method docs

„Extension Methoden, die Sie ermöglichen,‚‘Methoden zu bestehenden Typen hinzufügen, ohne einen neuen abgeleiteten Typen zu schaffen, neu zu kompilieren oder auf andere Weise die ursprüngliche Art zu modifizieren Extension-Methoden stellen eine besondere Art von statischer Methode dar, sie werden jedoch so aufgerufen, als wären sie 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 sind tatsächlich in einem Typ definiert. "

+0

Sie "neu" es auf die gleiche Weise wie Sie bereits - es bekommt magisch neue Methoden, die Sie haben hinzugefügt. – Bruce

+0

Erweiterungsmethoden sind nur dort gut, wo statische Methoden verwendet werden können. Außerdem muss der Namespace, der die Klasse mit den Erweiterungsmethoden enthält, ebenfalls enthalten sein. Zum Beispiel könnten Sie keine Eigenschaften haben, die den Status speichern. –

+0

Verstanden über den Staat - es gibt Einschränkungen. Ich verstehe Ihren Kommentar zu statischen Methoden nicht - sicher, die Erweiterungsmethode ist statisch, aber sie hat über den Parameter 'this' Zugriff auf die Objektinstanz. – Bruce

2

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.

5

Sie fragen: "Warum die Fähigkeit zur Unterklasse begrenzen?"

Da das Entwerfen für die Vererbung schwierig ist, besonders wenn Sie andere Entwickler entwerfen, die von Ihrer Klasse erben. Wie Josh Bloch in Effective Java sagt, sollten Sie die Vererbung entwerfen oder verbieten. Meiner Meinung nach sollten Sie, solange Sie keinen guten Grund haben, eine Erbschaft 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 hier oft keine wirklich elegante Antwort - 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.

1

Resharper hat eine nette Funktion, um delegierende Mitglieder zu erstellen.

Here ist ein Beispiel dafür, was Sie damit machen können. Es dauert ein paar Sekunden.

Verwandte Themen