2009-06-17 11 views
8

Pracuję z klasą C# innej firmy, która ma wiele wspaniałych metod i właściwości - ale z biegiem czasu muszę rozszerzyć tę klasę o metody i właściwości własne. Gdyby to był mój kod, po prostu użyłbym tej klasy jako mojej klasy bazowej i dodałbym własne właściwości i metodę na wierzchu - ale ta klasa ma wewnętrzny konstruktor. (Moim zdaniem było to nieduże, aby konstruktor był wewnętrzny w pierwszej kolejności - dlaczego ograniczać zdolność do podklasy?)Czy istnieje sposób wywodzenia się z klasy z wewnętrznym konstruktorem?

Jedyne, co mogłem wymyślić, to stworzyć metodę/właściwości na mojej klasie, która po prostu wywołała ich - ale to akry kodu i, cóż, po prostu nie "czuje" się dobrze.

Czy istnieje sposób użycia tej klasy jako klasy bazowej?

+1

Część pierwsza: http://blogs.msdn.com/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx –

+1

Część druga: http: //blogs.msdn .com/ericlippert/archive/2008/10/06/prevent-third-party-derivation-part-two.aspx –

Odpowiedz

0

Nie będę omawiać, czy możesz zbudować własną elewację wokół tej klasy. Poprzedni autor ma rację, bibliotekę można zaprojektować w sposób, który na to nie pozwoli. Załóżmy, że mają kilka połączonych klas, które mają single, które powinny zostać zainicjalizowane w określonej kolejności lub coś podobnego - może być dużo błędów w projektowaniu (lub funkcjach), których twórcy stron trzecich nigdy nie dbają, ponieważ nie sądzą, że użyjesz ich biblioteka w ten sposób.

Ale OK, załóżmy, że budowanie elewacji nie jest niemożliwym zadaniem, a ty masz tylko jeden problem - jest zbyt wiele metod, które musisz napisać owijki wokół numeru, i nie jest dobrze, aby to zrobić ręcznie.

widzę 3 rozwiązania w celu rozwiązania tego problemu dokładnie

1) Przypuszczam, że nowe „dynamiczne” typy .NET 4.0 pozwala na obejście tego problemu bez konieczności pisania „akrów kodem” Powinieneś Inkapsulate wystąpienie klasy 3rd party do klasy jako członek privare z dynamicznym słowem kluczowym Twoja klasa powinna pochodzić z Dynamic lub implementować interfejs IDynamicObject. Trzeba będzie wdrożyć GetMember funkcje/SetMember że przekaże wszystkie połączenia do odizolowanej instancji klasy 3rd party

Dobrze, C# 4.0 to przyszłość, Zobaczmy na inne rozwiązania:

2) Nie zapisuj kodu ręcznie, jeśli masz znaczną liczbę publicznych metod (powiedzmy więcej niż 100). Napisałbym małą aplikację konsolową, która używa odbicia i znajduje wszystkich publicznych członków, a następnie automatycznie generuje kod wywołujący enkapsulowaną instancję. Na przykład

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

3) Można zrobić tak samo jak 2, ale z pomocą istniejących narzędzi odbicie, na przykład RedGate .NET Reflector. Pomoże ci to wyświetlić wszystkie podpisy klas i metod. Następnie wklej to wszystko w programie Word, a proste makro VB pozwoli ci wygenerować ten sam kod, co w 2.Uwaga: jak tylko nie będziesz kopiował kodu, a jedynie podpisy metod kopiowania, które są publicznie dostępne , Nie sądzę, żebyś naruszył umowę licencyjną, ale w każdym razie warto ponownie sprawdzić:

2

Tylko jeśli twoja klasa mieszka w tym samym zespole, z którego chcesz dziedziczyć. Wewnętrzny konstruktor ogranicza konkretne implementacje klasy abstrakcyjnej do złożenia definiującego klasę. Klasa zawierająca wewnętrzny konstruktor nie może być utworzona poza złożeniem.

2

Brzmi jak idealny wniosku o sposobach rozszerzenia:

MSDN extension method docs

„Metody Przedłużacze pozwalają na«dodaj»metod do istniejących typów bez tworzenia nowego typu pochodnych, rekompilacji lub w inny sposób modyfikując oryginalny typ Metody rozszerzeń są szczególnym rodzajem metody statycznej, ale są wywoływane tak, jakby były metodami instancji typu rozszerzonego. Dla kodu klienta napisanego w C# i Visual Basic nie ma widocznej różnicy między wywołaniem metody rozszerzenia a metodami są faktycznie zdefiniowane w typie. "

+0

Po prostu "nowość" to tak samo jak już to robisz - w magiczny sposób dostaje nowe metody, które już posiadasz dodano do niego. – Bruce

+0

Metody rozszerzeń są dobre tylko w miejscach, w których można zastosować metody statyczne. Ponadto należy również uwzględnić przestrzeń nazw zawierającą klasę z metodami rozszerzeń. Np. Nie można mieć właściwości przechowujących stan. –

+0

Pojęty stan - istnieją ograniczenia. Nie rozumiem twojego komentarza na temat metod statycznych - na pewno metoda rozszerzenia jest statyczna, ale ma dostęp do instancji obiektu za pomocą "tego" parametru. – Bruce

2

Jeśli klasa ma wewnętrzny konstruktor i nie ma publicznych konstruktorów, sugeruje to, że projektanci nie zamierzali jej zdyskwalifikować. W takim przypadku można użyć enkapsulacji lub użyć metod rozszerzeń.

5

Pytasz: "Dlaczego ograniczać zdolność do podklasy?"

Projektowanie dla dziedziczenia jest trudne, zwłaszcza jeśli projektujesz dla innych programistów, którzy odziedziczą po klasie. Jak mówi Josh Bloch w Effective Java, powinieneś zaprojektować dziedziczenie lub zabronić tego. Moim zdaniem, chyba że masz dobry powód, by zaprojektować dziedziczenie, nie powinieneś robić tego spekulacyjnie.

Czy klasa implementuje interfejs, który można również zaimplementować (być może poprzez pośredniczenie w większości połączeń z powrotem do instancji oryginału)? Często nie ma tu naprawdę eleganckiej odpowiedzi - najlepsze rozwiązanie zależy od dokładnej sytuacji, w tym od tego, co próbujesz dodać do zajęć.

Jeśli nie dodajesz więcej stanów - po prostu wygodnych metod, efektywnie - wtedy metody rozszerzeń mogą dobrze działać. Nie zmieniają one jednak danych, które obiekt może przechowywać, więc jeśli trzeba dodać własne wyspecjalizowane dane, to nie zadziała.

1

Resharper ma fajną funkcję do tworzenia delegujących członków.

to próbka tego, co można z nim zrobić. To zajmuje kilka sekund.

Powiązane problemy