I've implemented modules cleaning up on application shutdown in the following way.
I create "cleanup service" where modules can register their cleanup actions.
public interface IModuleCleanupService
{
void RegisterCleanupAction(Action action);
}
public class ModuleCleanupService: IModuleCleanupService
{
private readonly List m_cleanupActions = new List();
public void RegisterCleanupAction(Action action)
{
m_cleanupActions.Add(action);
}
public void Cleanup()
{
List<Exception> exceptions = null;
foreach (Action action in m_cleanupActions)
{
try
{
action();
}
catch (Exception ex)
{
if (exceptions==null)
exceptions = new List<Exception>();
exceptions.Add(ex);
}
}
if (exceptions != null)
throw new AggregateException(exceptions);
}
}
Then any module can import IModuleCleanupService-instance. This can be done in different ways (with MEF/Unity via contructor injection or through asking the ServiceLocalor.Current)
The service's instance is created in Bootstapper's ConfigureContainer (here I'm using MefBootstapper deviced type, but this isn't important):
protected override void ConfigureContainer()
{
base.ConfigureContainer();
m_moduleCleanupService = new ModuleCleanupService();
Container.ComposeExportedValue<IModuleCleanupService>(m_moduleCleanupService);
}
Then I add GetDisposable method to my bootstapper which returns IDisposable-object. That IDisposable-object simple calls Cleanup on ModuleCleanupService:
public IDisposable GetDisposable()
{
return new DisposableDelegate(() => m_moduleInitializationService.Cleanup());
}
class DisposableDelegate: IDisposable
{
private readonly Action m_action;
public DisposableDelegate(Action action)
{
m_action = action;
}
public void Dispose()
{
m_action();
}
}