This project has moved. For the latest updates, please go here.

What is Event Based Components?

Event Based Components (EBC) is an architectural model which reduces dependencies between components. Components in EBC application communicate with each other by means of messages instead of invoking methods. Messages can be of any .NET type (such as string or some complex class). Components are wired together just like electronic components, pin to pin. Components may have input and output pins, and communication messages always flow from output pins to input pins. Technically, output pins are events and input pins are methods which take single message argument.

EBC communication requires the following:
  • Message types used for data transfer (should be serializable)
  • Component interfaces (used to generate client-side proxies)
  • Component classes (they should implement corresponding interfaces)

Interfaces and message types should be defined in the shared interface assembly known both to the client and the server (Shared Assembly). Component classes should be defined in an assembly which is only known to the server (Server-Assembly).

Here is a simple calculator example which shows how EBC applications could be built:

Shared Assembly

// Message type used by calculator EBC
[Serializable]
public class AdditionRequestMessage
{
    public decimal Number1 { get; set; }
    
    public decimal Number2 { get; set; }
}

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

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

// EBC implementation
public class Calculator : ICalculator
{
    // Input pin (consumes addition request messages)
    public void AddNumbers(AdditionRequestMessage request)
    {
        decimal result = request.Number1 + request.Number2;

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

    // Output pin (broadcasts addition result)
    public Action<decimal> Out_SendResult { get; set; }
}

Hosting EBCs

To make EBC calculator available to clients, you need to host it in ZyanHost just like ordinary non-EBC components:

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

Consuming EBCs

Client-side EBCs can be wired to remote EBC proxies just the same way as to the local components. Let's suppose we want to consume EBC calculator in a simple Windows Forms application. We create a form and add a few input controls:

Name Description
_textNumber1 Text field for the first summand
_textNumber2 Text field for the second summand
_buttonCalc Button which starts the calculation
_textResult Text field for the result


Client code looks as follows:

Client Assembly

public partial class CalcForm : Form
{
    // Output pin (to be wired to EBC calculator's input pin)
    public Action<AdditionRequestMessage> Out_AddNumbers { get; set; }

    public CalcForm() 
    {
        InitializeComponents();
    }

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

    // Input pin (to be wired with EBC calculator's output pin)
    public void ReceiveResult(decimal result)
    {
        _textResult.Text = result.ToString();
    }
}
Next, you must wire up two components (EBC calculator and input form) to enable message flow.

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

        // create EBC components and proxies
        var calculatorProxy = connection.CreateProxy<ICalculator>();
        var form = new CalcForm();

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

        // run the application
        System.Windows.Forms.Application.Run(form);
    }
}
Full source code for this example could be found in Examples folder.

Tip: For more information on EBC model, see EBC inventor Ralf Westphal's blog (German only) or check out brief Event-Based Components Overview written for codeplex EBC Tooling project.

Last edited Mar 27, 2011 at 2:57 PM by yallie, version 1

Comments

asdandRizzo Nov 16, 2016 at 7:47 AM 
```
// Task interface
public interface ICalculator
{
Task<decimal> AddNumbers(AdditionRequestMessage request);
}
```

What are configuration and guaranties of callback events delivery? Possibly one, only one or at least one?

Swifter Sep 10, 2013 at 6:53 PM 
Just found out the hard way that this solution will not work for WindowsRT apps because the .Net portable class libraries do not support the [Serializable] attribute, but instead require the DataContractSerializer.