/DelphiEventBus

Implementation of event bus pattern for Delphi XE

Primary LanguagePascalMIT LicenseMIT

DelphiEventBus

Implementation of event bus pattern for Delphi XE

EventBus is designed to provide interaction between different components, without increasing connectivity.

Features

  • Development
    • The type of event is determined by the class.
    • Events are inherited.
    • The base class for any event is TbtkEventObject.
  • Filtering
    • Events can contain filters.
    • Filter values are case sensitive.
    • To declare filters, annotations of event class methods are used.
    • As a filter, functions without parameters are used that should return the filter value as a string.
    • Filters are identified by name.
    • The filter name is specified in the filter annotation.
    • Filter names are not case sensitive.
    • Filters use two modes:
      • Simple mode.
        • The event filter value corresponds to empty and exactly matching handler filter values.
        • This mode is used by default.
      • Hashable mode.
        • The event filter value only matches exactly the same handler filter value.
        • Hashing accelerates the formation of lists of handlers to be called.
    • Filter mode is specified in the filter annotation.
    • The base class contains one hash filter named "Topic"
  • Handlers
    • Adding event handlers is done by registering a listener on the bus.
    • Removal of event handlers is performed by unregistration of the listener in the bus.
    • The filter values of listener event handlers are set after registration.
    • Filter values are bound to the event type, and are equal for different handlers of the same event.
    • To declare handlers, annotations of listener methods are used.
    • Handlers must contain one input parameter with the class type of the event being processed.
    • The type of the handler parameter determines the events that it will process.
    • The handler is invoked for all heirs of the event processed by it.
    • Two types of event handlers are used:
      • Simple handlers.
        • When calling, the filtering conditions are taken into account.
        • The order of the call is not guaranteed.
      • Hooks.
        • Called before calling simple handlers.
        • Ignore filtering conditions.
        • The order of the call corresponds to the reverse order of registration.
    • The type of handler will be determined by annotation.

Example of use

	//event class declaration
	Type
	  TFooEventObject = class(TbtkEventObject)
	  //..........................
	  public
	    const sFooFilterName = 'FooFilter';

	    constructor Create(ATopic: string; AFooFliter: string);

	    [EventFilter(sFooFilterName)] //filter parameter declaration
	    function FooFilter: string;

	  //..........................
	  end;

	//preparation of the listener
	  TFooEventListener = class
	  //..........................
	  public

	    [EventHandler] //handler declaration
	    procedure FooHandler(AFooEvent: TFooEventObject);

	    [EventHook] //hook declaration
	    procedure FooHook(AEventObject: TFooEventObject);

	  //..........................
	  end;

	  EventBus := TbtkEventBus.GetEventBus('FooEventBus');

	  ListenerInfo := EventBus.Register(FooEventListener);

	//setting filter parameters
	  ListenerInfo.HandlerFilters[TFooEventObject][TFooEventObject.sEventFilterTopicName].Value := 'TopicValue';
	  ListenerInfo.HandlerFilters[TFooEventObject][TFooEventObject.sFooFilterName].Value := 'FooFilterValue';

	//creating and sending events
	  EventBus.Send(TFooEventObject.Create('TopicValue', 'FooFilterValue'));

	//listener unregistration
	  EventBus.Unregister(FooListener);

Minimalistic example of use eventhook

	program EventHookExample;

        {$APPTYPE CONSOLE}

        uses
          System.SysUtils,
          btkEventBus;

        type
          TFooEventListener = class
          public
            [EventHook] //hook declaration
            procedure FooHook(EventObject: TbtkEventObject);
          end;

        { TFooEventListener }

        //hook implementation
        procedure TFooEventListener.FooHook(EventObject: TbtkEventObject);
        begin
          Writeln(Format('======'#13#10'Event with topic "%s" sended', [EventObject.Topic]));
        end;

        const
          ebFoo = 'FooEventBus';
        var
          FooEventListener: TFooEventListener;
          FooTopicName: string;
        begin
          //register class for eventbus with name 'FooEventBus'
          RegisterEventBusClass(TbtkEventBus, ebFoo);

          FooEventListener := TFooEventListener.Create;
          try
            //register listener
            EventBus(ebFoo).Register(FooEventListener);

            Write('Write topic: ');
            ReadLn(FooTopicName);

            //create and send event
            EventBus(ebFoo).Send(TbtkEventObject.Create(FooTopicName));
          finally
            FooEventListener.Free;
          end;
          Readln;
        end.

Minimalistic example of use eventhandler

	program EventHookExample;

        {$APPTYPE CONSOLE}

        uses
          System.SysUtils,
          btkEventBus;

        type
          TFooEventListener = class
          public
            [EventHandler] //handler declaration
            procedure FooHandler(EventObject: TbtkEventObject);
          end;

        { TFooEventListener }

        //handler implementation
        procedure TFooEventListener.FooHandler(EventObject: TbtkEventObject);
        begin
          Writeln(Format('Event with topic "%s" sended', [EventObject.Topic]));
        end;

        const
          FooTopicName = 'FooTopic';
        var
          FooEventListener: TFooEventListener;
          FooListenerInfo: TbtkListenerInfo;

        begin
          //register class for eventbus with empty name
          RegisterEventBusClass(TbtkEventBus);

          FooEventListener := TFooEventListener.Create;
          try
            //register listener and get listner info
            FooListenerInfo := EventBus.Register(FooEventListener);

            //set topicfilter for handler
            FooListenerInfo.HandlerFilters.Items[TbtkEventObject].Filters[TbtkEventObject.sEventFilterTopicName].Value := FooTopicName;

            //create and send event
            EventBus.Send(TbtkEventObject.Create(FooTopicName));
          finally
            FooEventListener.Free;
          end;
          Readln;
        end.