Benevia.Core.Events

Maintainers

  • @GlennEsh
  • @AkhmedovSanjar - Has a deep understanding of the event system and can provide insights into its design and functionality.

Introduction

Modules

Architecture

Logic containers

Logic containers contain the business logic for an entity or data type. Each entity or data type has a corresponding logic container class that holds its business logic methods. This is a singleton class that is instantiated once per application lifetime.

  • The logic container class is generated automatically based on the entity in the model. If the entity defined in the model is Contact, the logic container class will be Contact.Logic.
  • When the app starts up, logic is registered. This is done in a business logic class that is decorated with the [Logic] attribute and it can have one or more logic container parameters. Event methods must be decorated with the [RegisterLogic] attribute. Example:
[Logic]
public class ContactBL(Contact.Logic contact)
{
    [RegisterLogic]
    public void ContactBL()
    {
        // This method runs on startup. Add logic to the contact logic container here.
    }
}

Setup

<commands / code samples>

State

The State module tracks changes to entities and their properties during business logic execution.

Entity State

EntityState manages the overall state of entities and keeps track of all their properties.

customer._State.FullName.IsDirty; //If true, the FullName property will fire compute events when read.
customer._State.OriginalValue //Get original value of the entity before any changes.

Property State

PropertyState manages individual property changes with:

  • Original vs. new values
  • Validation status
  • Change tracking

This lets the system track what changed, validate data before saving, and manage property updates during business logic execution.

Base Event

BaseEvent provides common functionality for all events including event descriptions and tracing support for monitoring and debugging.

LogicBuilders

Logic builders provide a clean, readable way to define business logic using method chaining (Fluent).

Events Handler Pattern

Most event handlers follow a consistent pattern that accepts both the entity and the event arguments:

public delegate void SomeEventHandler<TEntity>(TEntity entity, SomeEventArgs args) where TEntity : IEntity, IEventEntity;

This allows subscribers to choose between a simple signature or a more detailed one:

  • .Do(entity => ...)
  • .Do((entity, args) => ...)

EventArgs Base Class

All event argument classes inherit from a common EventArgs base class, which provides utility methods to interact with the environment:

  • Context: Access the current EventContext.
  • GetService(): Resolve services from the scoped service provider.
  • GetEntities(): Access other entities via queryable.
  • GetEntity(id/key): Retrieve specific entities.

Example:

.Do((entity, args) => {
    var service = args.GetService<IMyService>();
    var otherEntities = args.GetEntities<OtherEntity>();
});