Funktion und Verwendung der Klasse ExpandoObject (Teil 4)
Kommentare

Compiler generiert notwendigen Code
Wie in den vorherigen Beispielen erläutert wurde, kann eine Instanz der Klasse ExpandoObject dynamisch um neue Mitglieder erweitert werden. Werden später die dynamisch

Compiler generiert notwendigen Code

Wie in den vorherigen Beispielen erläutert wurde, kann eine Instanz der Klasse ExpandoObject dynamisch um neue Mitglieder erweitert werden. Werden später die dynamisch hinzugefügten Mitglieder aufgerufen, muss jedoch eine Codebasis vorhanden sein, um eine Ausführung zu ermöglichen. Die Erstellung dieser Codebasis wird von dem Compiler übernommen. Listing 7 zeigt den generierten Code für die originale Methode Expando0.

Listing 7

public static void Expando0()
{
  dynamic person = new ExpandoObject();
  person.LastName = "Test";
  string test = person.LastName;
}
 [CompilerGenerated]
private static class o__SiteContainer0
{
    // Fields
    public static CallSite> <>p__Site1;
    public static CallSite> <>p__Site2;
    public static CallSite> <>p__Site3;
}
public static void Expando0()
{
    object person = new ExpandoObject();
    if (o__SiteContainer0.<>p__Site1 == null)
    {
        o__SiteContainer0.<>p__Site1 = 
        CallSite>
        .Create(Binder.SetMember(CSharpBinderFlags.None, 
            "LastName", typeof(Program), new CSharpArgumentInfo[] { 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | 
            CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
    }    
    o__SiteContainer0.<>p__Site1.
        Target(o__SiteContainer0.<>p__Site1, person, "Test");
    if (o__SiteContainer0.<>p__Site2 == null)
    {
        o__SiteContainer0.<>p__Site2 = 
        CallSite>.
        Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), 
        typeof(Program)));
    }
    if (o__SiteContainer0.<>p__Site3 == null)
    {
        o__SiteContainer0.<>p__Site3 = 
        CallSite>
        .Create(Binder.GetMember(CSharpBinderFlags.None, "LastName",
        typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo
            .Create(CSharpArgumentInfoFlags.None, null) }));
    }
    string test = o__SiteContainer0.<>p__Site2.
                      Target(o__SiteContainer0.<>p__Site2, 
                  o__SiteContainer0.<>p__Site3.Target
                      (o__SiteContainer0.<>p__Site3, person));
}  

Die dynamisch hinzugefügten Mitglieder werden innerhalb einer privaten statischen Klasse verwaltet. Der Compiler erzeugt dafür eindeutige Namen, um nicht mit bestehenden Bezeichnern zu kollidieren. In dem Beispiel wurde die Klasse o__SiteContainer0 angelegt, in denen notwendige CallSite-Instanzen verwaltet werden. Die zuvor einfache Methode Expando0 wurde vom Compiler erweitert, um die notwendigen CallSite-Instanzen zu erzeugen. Um die doppelte Erzeugung einer bereits gültigen CallSite zu vermeiden, prüft der Compiler zunächst, ob die betroffene Instanz noch null ist. Das Schlüsselwort dynamic wurde vom Compiler durch den Typ object ersetzt, da kein CLR Typ dynamic existiert. Im Folgenden werden die notwendigen CallSite- Instanzen generiert. Die CallSite p__Site1 definiert die Set-Eigenschaft für die dynamische Eigenschaft LastName. Wurde die CallSite angelegt, wird sie sofort aufgerufen, um den Wert der Eigenschaft zu setzen. Danach wird im Code der Wert der Eigenschaft ausgelesen, daher müssen nun die notwendigen CallSite-Instanzen für die Get-Eigenschaft erzeugt werden. Dafür sind zwei CallSite-Instanzen notwendig. Zum einen wird eine CallSite für die eigentliche Eigenschaft benötigt, und zum anderen muss der zurückgegebene Datentyp gebunden werden. Die CallSite-Instanz p__Site2 ist für die Bindung des Rückgabewerts verantwortlich, und p__Site3 definiert die eigentliche Get-Eigenschaft. Stehen beide CallSite-Instanzen bereit, werden sie am Ende aufgerufen. Würde die Eigenschaft lediglich ein object zurückgeben, würde die CallSite p__Site2 nicht benötigt.

Marc André Zhou arbeitet als Senior Consultant bei der Logica Deutschland GmbH & Co. KG. Seine Schwerpunkte liegen im Bereich SharePoint, Softwarearchitekturen und Frameworks, hier hauptsächlich im .NET-Umfeld. Sie erreichen ihn unter marc.andre.zhou@logica.com.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -