I've used the unit of work pattern to wrap my business logic. (Note that the application has three states: Logedout, LogedIn, Loaded)
public class LogoutUnitOfWork
{
public void Execute()
{
new UnloadUnitOfWork().Execute(false);
// navigate to the "logout view"
// do some business related work
// navigate to the "login view" (Logedout state)
}
}
public class UnloadUnitOfWork
{
public void Execute(bool navigate = true)
{
// navigate to the "unloading view"
// do some business related work
_legacyService.Unload();
if(navigate)
{
// => navigate to the "logedin view" (LogedIn state)
}
}
}
// not relevant for now
public class LoadUnitOfWork {}
public class LoginUnitOfWork {}
Until now non of the work units was directly listening to an event. I have place where I listen to domain events and execute an unit of work if nessesary.
public void ConfigureApplicationEvents()
{
_eventAggregator.GetEvent<TimeoutEvent>().Subscribe(() =>
{
new UnloadUnitOfWork().Execute();
}
...
}
Or I execute this unit of works from the UI (When a button was clicked).
But I have a legacy dependency which also publishes events. Now I have to listen to this events and then navigate to the view which represents the new state. The problem is that I do not know where the event came from.
_legacyService.Unloading += (sender, args) =>
{
// navigate to the "unloading view"
};
_legacyService.Unloaded += (sender, args) =>
{
// where should I navigate to?
// I need to know if the event came from the LogoutUnitOfWork, UnloadUnitOfWork or from the legacy dependency directly.
};
At the moment I solve this like the following:
var setShouldNavigateQueue = new Queue<Action>();
var shouldNavigate = true;
_legacyService.Unloading += (sender, args) =>
{
// navigate to the "unloading view"
};
_legacyService.Unloaded += (sender, args) =>
{
// do some buisiness related work
if (shouldNavigate)
{
// => navigate to the "logedin view" (LogedIn state)
}
// as the legacy service reports back after the unit of work events
// we execute the actions that have been queued
// (should be only one which sets `shouldNavigate` to the default value)
while (setShouldNavigateQueue.Any())
{
setShouldNavigateQueue.Dequeue().Invoke();
}
};
// this events come from the unit of work
_eventAggregator.GetEvent<UnloadingEvent>().Subscribe(navigateToTarget =>
{
// the unit of work knows if after the unloading a navigation should occure
// this navigation wonn't happen for example when the `LogoutUnitOfWork` was
// executed because it will navigate by itself
shouldNavigate = navigateToTarget;
});
_eventAggregator.GetEvent<UnloadedEvent>().Subscribe(() =>
{
// the unit of work reports first that the unloading is done
// push the action which sets the `shouldNavigate` to the default value into the queue
setShouldNavigateQueue.Enqueue(() => shouldNavigate = true);
});
public class LogoutUnitOfWork
{
public void Execute()
{
new UnloadUnitOfWork().Execute(false);
// navigate to the "logout in progress view"
// do some business related work
// navigate to the "login view" (Logedout state)
}
}
public class UnloadUnitOfWork
{
public void Execute(bool navigate = true)
{
_eventAggregator.GetEvent<UnloadingEvent>().Publish(navigate);
// navigate to the "unloading in progress view"
// do some business related work
_legacyService.Unload();
_eventAggregator.GetEvent<UnloadedEvent>().Publish();
}
}
But this is to hard to read and could be missleading to others.
- How could I change my code to make it simpler?
- Should I wait and also listen for this legacy events in my unit of work? (I would find this strange as the unit of work then could start by itself which is a concept not found yet in my app)
PS: If I let out any informations you need or if I wrote a little confusing please let me know that I can improve this post and my writing style.