Erzwingen des Aufrufs einer von C # abgeleiteten Methode

7

Ich habe eine Klasse, die von einem Werkzeug erzeugt wird, daher kann ich es nicht ändern. Die generierte Klasse ist sehr einfach (keine Schnittstelle, keine virtuellen Methoden):

%Vor%

Im C # -Projekt möchten wir einen Weg bieten, um eine andere Implementierung von MyFoo einbinden zu können. Also denke ich, MyFoo von GeneratedFoo

abgeleitet zu machen %Vor%

Dann habe ich eine CreateFoo-Methode, die entweder eine Instanz der Klasse GeneratedFoo oder MyFoo zurückgibt. Allerdings ruft es immer die Methode in GeneratedFoo auf.

%Vor%

Dies ist eine Ausnahme, da es keine virtuelle Methode ist. Aber ich frage mich, ob es einen Weg (vielleicht einen Hack) gibt, damit es die abgeleitete Methode nennt.

Danke, Danke Ian

    
Hengyi 13.08.2009, 23:45
quelle

7 Antworten

6

Ohne die Methode virtuell machen zu können, nein. Eine nicht virtuelle Methode ist zur Kompilierzeit statisch verknüpft und kann nicht geändert werden.

    
Adam Robinson 13.08.2009, 23:49
quelle
22

Adam hat dir eine Antwort gegeben (richtig). Jetzt ist es Zeit für Hack, nach dem du gefragt hast:)

%Vor%

Druckt aus:

%Vor%     
Marcin Deptuła 13.08.2009 23:54
quelle
6

Schreiben Sie eine Erweiterungsmethode, die Safecasts an Ihren abgeleiteten Typ sendet, und rufen Sie stattdessen die Methode diese -Referenz auf.

%Vor%

dann rufe es mit

auf %Vor%

NB : Das ist ein schmutziger Hack. Eine klarere Lösung wäre, sich selbst zu fragen, warum Sie den Modifikator new zuerst verwenden müssen. Wenn Sie die Bedeutung von Write(p) überladen, wird Ihr Code für Betreuer verwirrend. Sie könnten genauso gut public void WriteToTarget() oder etwas viel spezifischeres deklarieren, um diese Verwirrung zu vermeiden.

    
Tullo_x86 14.08.2009 00:11
quelle
3

Die Verwendung von "new" für eine Methode überschreibt nicht die ursprüngliche Methode. Dies ist völlig anders als Polymorphismus und sollte vermieden werden, sein einziger Zweck ist für die Kovarianz / Kontravarianz von Methoden, die eine identische Funktion ausführen (zB public Foo Clone () und public new Bar Clone ();). Der andere Zweck ist Legacy-Code, wenn eine Methode mit identischem Namen zu einer Basisklasse hinzugefügt wird, für die Sie keine Kontrolle haben und die den Namen Ihrer Methode zu diesem Zeitpunkt nicht ändern kann.

Obwohl die beiden Methoden den gleichen Namen haben, sind sie völlig separate Methoden. Sie belegen jedoch einen anderen Platz in der Methodentabelle der Klasse, wobei das Überschreiben die vorhandene Methode in der Methodentabelle einer Klasse ersetzt.

Meine Lösung wäre, eine Schnittstelle wie IFoo zu verwenden und entweder die generierte Klasse zu bearbeiten oder eine Proxy-Klasse zu verwenden, die alle Methodenaufrufe an eine Instanz von GeneratedFoo delegiert, um IFoo zu implementieren.

%Vor%     
Chris Chilvers 14.08.2009 00:06
quelle
1

Wenn die generierte Klasse keine virtuelle Methode hat, ist das nicht möglich. Wenn Sie das Werkzeug so ändern könnten, dass die Write-Methode als virtuell generiert wird, dann verwenden Sie in MyFoo das Schlüsselwort override anstelle von new, um die Write-Methode zu qualifizieren. Eine zweite Option wäre, ein Skript / Makro zu schreiben, um den Quellcode von GeneratedFoo zu ändern, nachdem das Tool ausgeführt wurde, um die Zeichenfolge "virtual" vor den gewünschten Methoden als Teil Ihres Build-Prozesses zu injizieren.

    
softveda 13.08.2009 23:54
quelle
0

Was ist mit einer benutzerdefinierten FX-Cop-Regel, die Ihrem Build-System hinzugefügt wurde?

    
Ian Ringrose 11.02.2010 09:39
quelle
-1

Ein Ansatz, den Sie verwenden könnten, wäre, einige neue Klassen zu definieren, die alle von GeneratedFoo abgeleitet sind; zB:

%Vor%

Damit können Sie Ihrer generierten Klasse im Wesentlichen virtuelle Methoden hinzufügen.

    
Chris Shaffer 13.08.2009 23:55
quelle

Tags und Links