Reputation: 10253
I have a WPF application built on top of PRISM.
When the user tries to close the application I need to check the dirty status of any loaded views.
I was hoping to enumerate a list of the loaded modules and ask them in turn whether it's OK to exit and save any changes, but I'm having trouble finding a list of references to the loaded modules.
The closest I could find was IModuleCatalog which gives me a list of modules, but not the actual object references these modules
Any suggestions on how I can do this?
Thanks in advance
Ian
Upvotes: 3
Views: 5927
Reputation: 606
According to answer from Shrike, I use a similar solution with sending events by IEventAggregator.
Firstly, I have simple event definition called ModulesDisposeRequested:
public class ModulesDisposeRequested : CompositePresentationEvent<object> { }
Then all modules, that need to be disposed are subscribing to this event:
// Module constructor
public ModuleA(IEventAggregator eventAggregator) {
var evnt = eventAggregator.GetEvent<ModulesDisposeRequested>();
if (evnt != null)
evnt.Subscribe(OnModulesDisposeRequested);
}
private void OnModulesDisposeRequested(object payload) {
// cleanup current module
}
When application is about to finish, bootstrapper publish this event:
// Overring in App.xaml.cs
protected override void OnExit(ExitEventArgs e) {
var eventAggregator = _bootstrapper.Container.Resolve<IEventAggregator>();
var evnt = eventAggregator.GetEvent<ModulesDisposeRequested>();
if (evnt != null)
evnt.Publish(null);
base.OnExit(e);
}
Upvotes: 1
Reputation: 9500
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<Action> m_cleanupActions = new List<Action>();
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();
}
}
Upvotes: 2
Reputation: 50323
If what you want to do is to obtain the existing instance of all the loaded modules, you can do the following:
IServiceLocator
from the Unity container.ModuleInfo
in the module catalog where the state is Initialized
, get the module instance by using serviceLocator.GetInstance(moduleInfo.ModuleType)
Upvotes: 0
Reputation: 25650
Have you considered a composite command for this, rather than your current approach? It seems like your views ought to be participating in the closing of the application, rather than some central bit of module logic.
This sample (called the Commanding Sample, which I think is great to say... it's very commanding) illustrates a "Save All" which is very similar to your "Close All" (basically what you are doing). The thing that is great here is that this is functionality baked in that you don't have to build yourself: http://msdn.microsoft.com/en-us/library/dd458890.aspx
Upvotes: 4