Was sind Event Based Components?

Es handelt sich dabei um Architekturmodell, welches direkte Abhängigkeit reduzieren und die Zusammensteckbarkeit von Komponenten erhöhen soll. Event Based Components (EBC) kommunizieren miteinander über Nachrichten, statt direkt Methoden aufzurufen. Eine Nachricht kann ein beliebiger .NET Typ sein (z.B. ein String oder ein eigenes komplexes Objekt). Die einzelnen Komponenten in einer EBC-Anwendung werden über sog. Pins miteinander "verdrahtet". Es wird zwischen Eingangs- und Ausgangspins unterschieden. Nachrichten fließen stets von einem Ausgangspin zu einem Eingangspin. Ausgangspins werden im Code durch Delegaten und Eingangspins durch Methoden abgebildet.

Eine einzelne EBC besteht aus folgenden Bestandteilen:
  • Nachrichtenklassen für den Datenaustausch (Müssen serialisierbar sein, damit übers Netzwerk übertragbar)
  • Komponenten-Schnittstelle (wichtig für Proxy-Generierung auf entfernten Clients)
  • Komponenten-Implementierung (muss die Komponenten-Schnittstelle implementieren)

Schnittstelle und Nachrichtenklassen müssen in eine Assembly gepackt werden, die Client und Server gleichermaßen bekannt sind (Shared-Assembly). Die eigentliche Komponenten-Implementierung kann entweder direkt in der Assembly des Server-Prozesses (Server-Assembly) oder in einer separaten Assembly untergebracht werden, die nur dem Server bekannt ist.

Am folgenden Beispiel eines sehr einfaches Additions-Rechners, sieht man, wie EBCs aufgebaut sind.

Shared-Assembly

// Nachrichtenklasse für Additionsanfrage
[Serializable]
public class AdditionRequestMessage
{
    public decimal Number1 { get; set; }
    
    public decimal Number2 { get; set; }
}

// Komponentenschnittstelle
public interface ICalculator
{
    void AddNumbers(AdditionRequestMessage request);

    Action<decimal> Out_SendResult { get; set; }
}
Server-Assembly

// Komponenten-Implementierung
public class Calculator : ICalculator
{
    // Eingangspin (Nimmt Zahlen für die Addition entgegen)
    public void AddNumbers(AdditionRequestMessage request)
    {
        decimal result = request.Number1 + request.Number2;

        if (Out_SendResult!=null)
            Out_SendResult(result);
    }

    // Ausgangspin (Sendet das Ergebnis der Addition zurück)
    public Action<decimal> Out_SendResult { get; set; }
}

EBC hosten

Damit die EBC Calculator von entfernten Clients konsumiert werden kann, muss sie zunächst mit Zyan gehostet werden. Dies funktioniert ganz genauso, wie mit herkömmlichen Klassen auch.

ZyanComponentHost host = new ZyanComponentHost("CalculatorApp",8080);
host.RegisterComponent<ICalculator, Calculator>(ActivationType.SingleCall);

EBC konsumieren

Auf der Clientseite lebende EBCs werden einfach mit den Proxies entfernter EBCs verdrahtet. Ganz genauso, wie man auch lokale EBCs miteinander verdrahten würde.
Angenommen wir haben eine clientseitige EBC, die eine Benutzeroberfläche für die entfernte Calculator EBC als Windows.Forms-Formular implementiert. Auf dem Formular sind folgende Steuerelemente platziert:

Membervariable Beschreibung
_textNumber1 Textfeld für die 1. Zahl
_textNumber2 Textfeld für die 2. Zahl
_buttonCalc Knopf, der die Berechnung startet
_textResult Textfeld für das Ergebnis

Der Code des Formulars sieht folgendermaßen aus:

Client-Assembly

public partial class CalcForm : Form
{
    // Ausgangspin (Sendet die zu addierenden Zahlen an die Berechnungskomponente)
    public Action<AdditionRequestMessage> Out_AddNumbers { get; set; }

    public CalcForm() 
    {
        InitializeComponents();
    }

    private void _buttonCalc_Click(object sender, EventArgs e)
    {
        if (Out_AddNumbers!=null)
            Out_AddNumbers(new AdditionRequestMessage() 
            {
                Number1 = decimal.Parse(_textNumber1.Text),
                Number2 = decimal.Parse(_textNumber2.Text)
            });
    }

    // Eingangspin (Empfängt das Ergebnis)
    public void ReceiveResult(decimal result)
    {
        _textResult.Text = result.ToString();
    }
}
Damit die Nachrichten fließen können, müssen beide Komponenten noch verdrahtet werden.

static class Program
{
    static void main()
    {
        ZyanConnection connection = new ZyanConnection("tcp://localhost:8080/CalcuatorApp");

        // Komponenten bzw. Proxies erzeugen
        ICalculator calculatorProxy = connection.CreateProxy<ICalculator>();
        CalcForm form = new CalcForm();

        // Verdrahten
        form.Out_AddNumbers = Asynchronizer<AdditionRequest>.WireUp(new Action<AdditionRequest>(proxy.In_AddNumbers));
        proxy.Out_SendResult = SyncContextSwitcher<decimal>.WireUp(new Action<decimal>(form.In_ReceiveResult));        

        System.Windows.Forms.Application.Run(form);
    }
}
Den kompletten Quellcode dieses Beispiels finden Sie in der Quellcodeverwaltung im Ordner Examples.

Detaillierte Informationen, Beispiele und Varianten des EBC-Konzepts, finden Sie im Weblog des EBC-Erfinders Ralf Westphal.

Last edited Mar 21, 2011 at 12:56 PM by yallie, version 12

Comments

No comments yet.