Funktion und Verwendung der Klasse ExpandoObject (Teil 3)
Kommentare

Wie die Methode PrintFullName verdeutlicht, kann innerhalb der Methode über this auf Objekteigenschaften, Felder oder Methoden nicht direkt zugegriffen werden. Um das zu ermöglichen, muss das Objekt

Wie die Methode PrintFullName verdeutlicht, kann innerhalb der Methode über this auf Objekteigenschaften, Felder oder Methoden nicht direkt zugegriffen werden. Um das zu ermöglichen, muss das Objekt explizit der Methode übergeben werden. Die Methode GetFullName zeigt darüber hinaus die Umsetzung einer dynamischen Methode mit Rückgabewert. Einer Instanz vom Typ ExpandoObject können auch dynamisch Ereignisse hinzugefügt werden. Listing 5 zeigt die dafür notwendige Vorgehensweise und erweitert die dynamische Personenklasse um das Ereignis PrintedFullName, das immer dann ausgelöst wird, wenn die Methode PrintFullName aufgerufen wurde.

Listing 5

public static void Expando4()
{
  // ... ausgelassen ...
  dynamic person = new ExpandoObject();
  // ... ausgelassen ...
  person.PrintFullName = new Action((p) =>
  {
    Console.WriteLine("Mein Name ist: {0} {1} {2}", 
                      p.Salutation, p.FirstName, p.LastName);
    // Auslösen des Ereignisses, wenn es abonniert wurde.
    EventHandler e = p.PrintedFullName;
    if (e != null)
      e(p, EventArgs.Empty);
  });
  // Binden an das Ereignis 'PrintedFullName'
  person.PrintedFullName = null;
  person.PrintedFullName += new EventHandler(HandleUpdatedEvent);
  person.PrintFullName = new Action((p) =>
  {
    Console.WriteLine("Mein Name ist: {0} {1} {2}", 
                       p.Salutation, p.FirstName, p.LastName);
  });
}
static void HandleUpdatedEvent(object sender, EventArgs e)
{
  Console.WriteLine("Method 'PrintedFullName' executed. Object:  {0}", sender);
}  

Interne Funktionsweise

Die interne Funktionsweise wird am deutlichsten, wenn eine eigene erweiterbare Klasse realisiert wird. Die eigene Klasse muss dazu von der Klasse DynamicObject ableiten. Listing 6 zeigt eine einfach gehaltene Implementierung.

Listing 6

public class CustomExpando : DynamicObject
{
  private Dictionary members = new Dictionary();
  public override bool TrySetMember(SetMemberBinder binder, object value)
  {
    if (!members.ContainsKey(binder.Name))
      members.Add(binder.Name, value);
    else
      members[binder.Name] = value;
    return true;
  }
  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
    result = null;
    if (!members.ContainsKey(binder.Name))
      return false;
    result = members[binder.Name];
    return true;
  }
  public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, 
                                        out object result)
  {
    Delegate func = members[binder.Name] as Delegate;
    result = func.DynamicInvoke(args);
    return true;
  }
}  

Intern werden dynamisch hinzugefügte Mitglieder in einem simplen Key/Value-Dictionay gespeichert. Die Methode TrySetMember fügt dem späteren Objekt ein neues Mitglied hinzu. Alle wesentlichen Aufrufinformationen des übergebenen Mitglieds (Eigenschaft, Methode oder Ereignis) enthält der erste Parameter vom Typ SetMemberBinder. Der zweite Parameter value vom Typ object enthält, wenn es sich um eine Eigenschaft handelt, den zugehörigen Wert der Eigenschaft. Wird dem Objekt eine Methode hinzugefügt, enthält der zweite Parameter den definierten Funktionszeiger (Delegate). Für den Abruf eines Eigenschaftswerts ist die Methode TryGetMember zuständig. Die Methode bezieht den aktuellen Wert der angeforderten Eigenschaft aus dem internen Dictionary und gibt ihn über Ausgabeparameter (out) result zurück. Der Aufruf einer dynamisch hinzugefügten Methode geschieht über die Methode TryInvokeMember. Aus dem internen Dictionary wird der gespeicherte Funktionszeiger ermittelt. Als Schlüssel dazu dient der Name der aufzurufenden Methode. Anschließend wird die Methode mittels DynamicInvoke, der auch die zugehörigen Parameter übergeben werden, aufgerufen. Ein unter Umständen vorhandener Rückgabewert wird über den result-Parameter zurückgegeben.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -