Watching
Watchers can be configured for watching scenarios in the Director
. Watchers can act on events which are fired in the scenario. All scenarios trigger 4 events by default: Before, Playing, Ending and After.
SceneWatcher
A SceneWatcher is used for watching events for a specific scenario. It will be implemented like this:
public class ShipmentWatcher : ISceneWatcher<FullFill>
{
public void Watch(FullFill scenario)
{
scenario.Ending += (_, _) =>
{
Another pattern can be to use a generic scenewatcher. This way you can implement generic logic for a watcher, but it still is only registered for a specific scenario. An example of such a watcher can be found in the paragaph below.
BingeWatcher
A BingeWatcher is used for watching events for a every scenario. This could be useful when events which get triggered in multiple scenarios needs to be handled in the same way.
Examples
In this example a scenario with 2 operations fires an event when the first operation is done. In addition an example of a SceneWatcher is made. This SceneWatcher will be logging the results from the first operation.
Step 1: Add EventHandler
In the code below the property Operation1Executed
is added to the scenario Calculate
. When the first operation is done the scenario fires the event.
[Scenario(typeof(Calculate))]
public class Calculate : Scenario<IFormula, decimal>
{
public Func<int, int, decimal> Operate { get; set; }
public event EventHandler<EventArgs> Operation1Executed;
public Calculate(IFormula role) : base(role)
{
}
protected override decimal Exec()
{
var operation1Result = Operate.Invoke(Role.Number1, Role.Number2);
Fire(Operation1Executed, nameof(Operation1Executed), new OperationEventArgs(operation1Result));
return SecondOperation(operation1Result);
}
private static decimal SecondOperation(decimal number)
{
return number * 2;
}
}
In the OperationEventArgs the arguments are given for the event. In this example only a decimal is used as argument.
public class OperationEventArgs : EventArgs
{
public readonly decimal OperationResult;
public OperationEventArgs(decimal operationResult)
{
OperationResult = operationResult;
}
}
Step 2: Create the SceneWatcher
The example is watching to 3 events from the Calculate
scenario. It logs a message before the scenario starts playing, when the first operation is done and lastly after the scenario has ended.
public class CalculateWatcher : ISceneWatcher<Calculate>
{
private readonly ILogger<CalculateWatcher> _logger;
public CalculateWatcher(ILogger<CalculateWatcher> logger)
{
_logger = logger;
}
public void Watch(Calculate scenario)
{
scenario.Before += (sender, args) =>
{
var message = $"Calculate started";
_logger.LogInformation(message);
};
scenario.Operation1Executed += (sender, args) =>
{
var message = $"{nameof(scenario.Operation1Executed)} with value: {args.OperationResult}";
_logger.LogInformation(message);
};
scenario.After += (sender, args) =>
{
var message = $"Calculate ended";
_logger.LogInformation(message);
};
}
}
Step 3: Configure the Director
Lastly, the SceneWatcher needs to be configured in the Director
.
public static void InviteWatchers(ContainerBuilder builder)
{
builder.RegisterType<CalculateWatcher>()
.As<ISceneWatcher<Calculate>>();
}
Generic scene watcher
An example of a generic watcher is the Mailwatcher. It can watch basically every scenario and send mails based on that scenario. It's implemented like this:
public class MailWatcher<TScenario> : ISceneWatcher<TScenario>
where TScenario : IScenario
{
public void Watch(TScenario scenario)
{
scenario.After += (sender, obj) =>
{
And registered inside the director like below. And in this case a mail is used when calculate is finished.
builder.RegisterType<Chaplin.Services.Postmark.MailWatcher<Calculate>>()
.As<ISceneWatcher<Calculate>>();
Last modified: 20 August 2024