I'm upgrading a Plugin Loading Engine (.NET
) which does the following :
All the plugins implement the same Interface : IPlugin
and each one is launched in a separate BackGroundWorker
. All the BackgroundWorkers
are managed by a module called Host
.
My problem is the Errors/Exceptions Handling
. The engine is already deployed and I want to find an elegant way to handle the Errors/Exceptions
that could be thrown when the plugins run. Some Exceptions
are caught in the plugins but not all of them.
I was thinking about a separate layer that could catch the errors and treat them for all the plugins.
I imagined a kind of Context
attached to each Plugin
which contain its progress level (BackgroundWorker.ReportProgress
), its status, the thrown exceptions(using the RunWorkerCompletedEvent
) but the errors are thrown only after the BackgroundWorker
stops. I would like to interrupt it when an exception is thrown.
I was also thinking that Aspect Oriented Programming could be a great way. I took a look on the net and found some framework like Spring.NET. But not sure if it could be appropriate in my case.
[UPDATE] Here are more design details as requested :
AbstractEnvChecker
:The application is a Rich Client App. After compiling the plugins, the generated DLL
are loaded and a List is displayed to the users in a simple Windows Form. The user selects then the plugins to launch and the Plugin.DoWork()
method is called.
And here is how the Host launches the selected Plugins :
void LaunchPlugin(AbstractEnvChecker p_Plugin)
{
if (p_Plugin != null)
{
BackgroundWorker l_BackgroundWorker = new BackgroundWorker();
l_BackgroundWorker.WorkerReportsProgress = true;
l_BackgroundWorker.WorkerSupportsCancellation = true;
l_BackgroundWorker.DoWork +=
new DoWorkEventHandler(bw_DoWork);
l_BackgroundWorker.ProgressChanged +=
new ProgressChangedEventHandler(bw_ProgressChanged);
l_BackgroundWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
m_PluginByThreadMap.Add(l_BackgroundWorker, p_Plugin);
l_BackgroundWorker.DoWork += p_Plugin.DoWork;
l_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(l_BackgroundWorker_RunWorkerCompleted);
l_BackgroundWorker.RunWorkerAsync(p_Plugin);
}
}
Is AOP
an appropriate solution to add the Error Handling Layer ?
The simplest way would be to just wrap the IPlugin.DoWork()
method in a try/catch
clause. something like this:
l_BackgroundWorker.DoWork += (o, e) => ExecutePlugin(o, e, p_plugin);
private void ExecutePlugin(object sender, DoWorkEventArgs e, IPlugin plugin)
{
try
{
plugin.DoWork(o, e);
}
catch (Exception e)
{
//do something with the error. disable the plugin maybe?
}
}
If this work then using Spring just for the Error handling is a bit overkill in my opinion.
Something additional you could do is throwing a custom exception (e.g. a PluginException
) and handle those globally in your Application, this can be achieved by attaching to:
Application.ThreadException
and AppDomain.CurrentDomain.UnhandledException
events