Search code examples
c#.netexceptionaopspring.net

Exception Handling : AOP vs Classic Handling?


I'm upgrading a Plugin Loading Engine (.NET) which does the following :

  1. Loads Plugins
  2. Connects them to the appropriate Data Source
  3. Launchs the Plugins
  4. Displays the results

All the plugins implement the same Interface : IPluginand 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 :

  • IPlugin Interface : Called AbstractEnvChecker :

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 ?


Solution

  • 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