10.9 Dynamisches Binden
Seit der Version 4.0 hat C# auch die Fähigkeit, das sogenannte späte Binden zu realisieren. Was ist darunter zu verstehen? Schauen wir uns dazu einmal das folgende Beispiel an:
class Program {
static void Main(string[] args) {
Mathematics math = new Mathematics();
long result = math.Addition(56, 88);
}
}
class Mathematics {
public long Addition(int x, int y) {
return x + y;
}
}
Listing 10.49 Statisches Binden
Die Klasse Mathematics wird instanziiert, ein statischer Vorgang, der bereits zur Kompilierzeit durchgeführt wird.
Mit Hilfe der Reflection ließ sich ein solcher Aufruf auch früher schon dynamisch formulieren, wie das folgende Listing zeigt.
object math = new Mathematics();
Type mathType = math.GetType();
object obj = mathType.InvokeMember("Addition",
BindingFlags.InvokeMethod,
null,
math,
new object[] { 56, 88 });
long result = (long)obj;
Listing 10.50 Dynamisches Binden mit der Reflection
Das Listing setzt voraus, dass der Namespace System.Reflection mit using bekannt gegeben worden ist.
Das Resultat des Konstruktoraufrufs von Mathematics wird einer Variablen vom Typ Object zugewiesen. Darauf besorgt man sich den Type des Objekts und ruft darauf die Methode InvokeMember auf. Unter Übergabe des Methodenbezeichners, des Elementtyps, der Referenz des abzurufenden Objekts und der Argumente für den Methodenaufruf wird ein Resultat gebildet, das am Ende nur noch in den Ergebnistyp long konvertiert werden muss.
Dieses Coding lässt sich unter Zuhilfenahme des Schlüsselworts dynamic auch deutlich kürzer ausdrücken:
dynamic obj = new Mathematics();
long result = obj.Addition(56, 88);
Listing 10.51 Dynamisches Binden mit »dynamic«
Das dynamic-Schlüsselwort wird zur Kompilierzeit statisch geprüft. Die Methode Addition hingegen ist dynamisch und wird nicht zur Kompilierzeit geprüft. Natürlich werden Sie auch keine IntelliSense-Hilfe nach dem Punktoperator nutzen können, Sie müssen die Methode Addition manuell angeben.
Bei obj handelt es sich um ein dynamisches Objekt, der Aufruf der Methode selbst ist dynamisch und wird erst zur Laufzeit geprüft.
10.9.1 Eine kurze Analyse

Lassen Sie uns an dieser Stelle eine Betrachtung hinsichtlich der Objektvariablen durchführen und diese direkt miteinander vergleichen. Sie kennen mit dem in diesem Abschnitt beschriebenen Schlüsselwort dynamic inzwischen drei Varianten:
- Object myObject = new Mathematics();
- var myObject = new { [...] };
- dynamic myObject = new Mathematics();
Die zuerst aufgeführte Instanziierung deklariert eine Variable vom Typ Mathematics. Die Variable ist vom Typ Object, der Code ist streng typisiert. Sie können der Variablen jedes Objekt zuweisen, vorausgesetzt, es ist vom Typ Object und bekannt.
Flexibler ist bereits der zweite Ausdruck. Auch hier liegt eine strenge Typisierung vor, aber der Typ muss erst zur Laufzeit gebildet werden. Typischerweise handelt es sich dabei um anonyme Typen, die zur Kompilierzeit gebildet werden.
Auch die letzte Variante mit dynamic wird sehr wohl auch statisch geprüft, aber der Aufruf auf die dynamic-Variable erfolgt dynamisch. Zur Kompilierzeit steht noch nicht fest, welche Operationen mit dem Typ ausgeführt werden. Daher ist auch keine IntelliSense-Hilfe sichtbar.
10.9.2 Dynamische Objekte
Mit der Einführung des Schlüsselworts dynamic wurden auch einige Klassen zum .NET Framework hinzugefügt, die auf dynamic aufsetzen. Diese Klassen befinden sich im Namespace System.Dynamic. Am interessantesten scheint hier die Klasse DynamicObject zu sein, mit der Klassen zur Laufzeit dynamisch erweitert werden können. Sie müssen die Klasse ableiten und können die abgeleitete Klasse zur Laufzeit um Objekteigenschaften erweitern und diese abrufen. Sehen wir uns das im folgenden Beispielprogramm an.
// Beispiel: ..\Kapitel 10\DynamicObjects
using System;
using System.Dynamic;
using System.Collections.Generic;
using System.Reflection;
class Program {
static void Main(string[] args) {
dynamic pers = new Person();
pers.Name = "Peter";
pers.Alter = 12;
pers.Ort = "Bonn";
pers.Telefon = 0181812345;
Console.WriteLine("{0}, {1}, {2}, {3}", pers.Name, pers.Alter, pers.Ort,
pers.Telefon);
Console.ReadLine();
}
}
class Person : DynamicObject {
Dictionary<string, Object> dic = new Dictionary<string, object>();
public string Name { get; set; }
public int Alter { get; set; }
public override bool TryGetMember(GetMemberBinder binder,
out object result) {
return dic.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
dic[binder.Name] = value;
return true;
}
}
Listing 10.52 Dynamische Objekte
Es ist die Klasse Person definiert, die die Klasse DynamicObject ableitet. Mit Name und Alter sind zwei Eigenschaften konkret festgelegt. Darüber hinaus enthält die Klasse Person ein Feld vom Typ der generischen Klasse Dictionary<>. Hierbei handelt es sich um eine generische Collection, in der alle Daten mit Hilfe eines Schlüssel-Werte-Paares beschrieben werden.
Das Dictionary<>-Objekt speichert Eigenschaften, die zur Laufzeit festgelegt werden. In Main sind das zum Beispiel die beiden Eigenschaften Ort und Telefon eines Person-Objekts, das zuvor mit dynamic erstellt wird – eine Voraussetzung für alle Typen, die von DynamicObject abgeleitet sind.
Damit die dynamischen Eigenschaften sich auch in das Objekt eintragen können, sind die beiden geerbten Methoden TrySetMember und TryGetMember überschrieben. Beide weisen mit GetMemberBinder und SetMemberBinder sehr ähnliche erste Parameter auf, die den dynamischen Member repräsentieren. Der Bezeichner der dynamischen Eigenschaft ist in der Eigenschaft Name der beiden Binding-Objekte zu finden.
Interessant werden dürfte die Klasse DynamicObject vermutlich in Zukunft im Zusammenhang mit Daten, deren Strukturen nicht vorhersehbar sind oder sich von Fall zu Fall ändern. In diesem Zusammenhang sei an die Tabellen einer Datenbank erinnert. Wie einfach ließen sich die Felder durch dynamische Member eines DynamicObject-Objekts beschreiben?
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.