Entwickler-Ecke

C# - Die Sprache - Typecast zur Laufzeit


UGrohne - Mo 23.10.06 14:39
Titel: Typecast zur Laufzeit
Hallo,
ich muss ein Objekt zur Laufzeit in einen zur Entwicklungszeit noch unbekannten Typ casten. Ich habe den Typ und eine Variable mit der Elternklasse des Objekts:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
            string result = "";
            foreach (UpdateItem item in updateItems)
            {
                System.Type type;
                Classes.TryGetValue(item.node.Name, out type);
                
                result += item.Update();
            }
            return result;

An der markierten Stelle muss ich nun item in die in type hinterlegte Klasse casten. Gibt es dafür eine Möglichkeit?


Kha - Mo 23.10.06 16:39

Dazu solltest du erst einmal beschreiben, wofür du das Objekt casten willst ;) . Geht es darum, die Methode Update der abgeleiteten Klasse aufzurufen? Wenn ja, wirst du wohl einen Grund haben, das nicht per OOP zu regeln, musst deswegen aber auf Reflection => MethodInfo.Invoke zurückgreifen.


UGrohne - Mo 23.10.06 17:49

user profile iconKhabarakh hat folgendes geschrieben:
Dazu solltest du erst einmal beschreiben, wofür du das Objekt casten willst ;) . Geht es darum, die Methode Update der abgeleiteten Klasse aufzurufen? Wenn ja, wirst du wohl einen Grund haben, das nicht per OOP zu regeln, musst deswegen aber auf Reflection => MethodInfo.Invoke zurückgreifen.

Ich habe eine Basis-Klasse, die bestimmte Eigenschaften zur Verfügung stellt und je nach Anwendungszweck wird eine Subklasse davon entwickelt, die die Verarbeitungsanforderungen erfüllt. Doch soll das Ganze auch ovn außen erweiterbar sein, deswegen kann ich diesen Typecast nicht hart codieren, z.B. über cases.

Das Erzeugen funktioniert bereits einwandfrei. Die Anweisung für einen Typ liegen in einer XML-Datei, daher kenne ich die Klasse, die erzeugt werden muss. Jetzt muss ich eben auf die Methoden dieser Klasse zurückgreifen können. Mit obigem Code bekomme ich natürlich nur die Update-Anweisung der Basis-Klasse ausgeführt, deswegen muss ich wohl auf Deinen Tipp zurückgreifen. Ich werde das nachher mal probieren, aber vielleicht hast Du noch eine bessere Idee, wie ich mein Ziel erreichen könnte?


r2c2 - Mo 23.10.06 18:38

user profile iconUGrohne hat folgendes geschrieben:
Mit obigem Code bekomme ich natürlich nur die Update-Anweisung der Basis-Klasse ausgeführt, [...]

Wenn die Methode überschrieben wird nicht. Oder hab ich dein Problem falsch verstanden? :gruebel:

mfg

Christian


UGrohne - Mo 23.10.06 19:04

user profile iconr2c2 hat folgendes geschrieben:
Wenn die Methode überschrieben wird nicht. Oder hab ich dein Problem falsch verstanden? :gruebel:

UpdateItem ist die Basisklasse, von der alle Erweiterungsklassen abgeleitet werden. Daher wird offensichtlich die Update-Methode der Klasse UpdateItem aufgerufen und nicht der abgeleiteten Klasse UpdateFile (in diesem Fall). Die Methode habe ich natürlich in der abgeleiteten Klasse überschrieben.

//EDIT: Ich habe schon an meinen OOP-Kenntnissen gezweifelt. Ich hatte vergessen bei der abgeleiteten Klasse override hinzuzufügen ;)
Danke trotzdem


Christian S. - Mo 23.10.06 19:06

Wenn Du die Methode in der Basisklasse als virtuell (oder gar abstrakt) deklarierst, dann wird die Methode der instanzierten Klasse aufgerufen und nicht die Methode der deklarierten Klasse.

//Edit: Hm, zu spät.


UGrohne - Mo 23.10.06 19:28

user profile iconChristian S. hat folgendes geschrieben:
Wenn Du die Methode in der Basisklasse als virtuell (oder gar abstrakt) deklarierst, dann wird die Methode der instanzierten Klasse aufgerufen und nicht die Methode der deklarierten Klasse.

//Edit: Hm, zu spät.

Man darf aber nicht das Schlüsselwort override vergessen ;)


Christian S. - Mo 23.10.06 19:39

Gibt das nicht 'ne Warnung vom Compiler? :gruebel:


UGrohne - Mo 23.10.06 19:47

user profile iconChristian S. hat folgendes geschrieben:
Gibt das nicht 'ne Warnung vom Compiler? :gruebel:

Doch, aber die überseh ich im Moment noch gerne, weil es noch so viele sind ;) Bin erst noch am Anfang der Entwicklung.


Robert_G - Mo 23.10.06 19:58

Ich habe echt keinen Plan wofür du den Typ da brauchst, aber eines fällt mir immer wieder auf.
Oft zwingen sich Programmierer in eine Vererbungspflicht, die nicht sein muss.
Gehe auf deine Basisklasse und mache ein Rechtsklick->Refactoring->Extract Interface.
Markiere die Member, die dich interessieren und benutze fortan nur noch dieses Interface.
Du kannst deine alte Basisklasse behalten und somit auch weiterhin Funktionalität erben, aber du musst es nicht mehr. :)
Außerdem haben interface instanzen den Vorteil, dass du die Kosten für virtual method dispatch pro call auf einen interface dispatch pro Instanz reduzierst.
Mag lächerlich kleinkariert klingen macht sich aber genau bemerkbar wie das versiegeln von Klassen.


UGrohne - Di 24.10.06 10:25

OK, danke für den Hinweis. Das werde ich mir genauer anschauen, ob ich das so umsetzen kann.