3

次のことを行うPlugin Loading Engine ( ) をアップグレード.NETしています。

  1. プラグインをロードします
  2. それらを適切なデータソースに接続します
  3. プラグインを起動します
  4. 結果を表示します

すべてのプラグインは同じ Interface を実装しておりIPlugin、各プラグインは個別の で起動されBackGroundWorkerます。これらはすべて、BackgroundWorkersというモジュールによって管理されますHost

私の問題はErrors/Exceptions Handling. Errors/Exceptionsエンジンは既にデプロイされており、プラグインの実行時にスローされる可能性のあるを処理するエレガントな方法を見つけたいと考えています。一部Exceptionsはプラグインに引っ掛かりますが、すべてではありません。

エラーをキャッチしてすべてのプラグインで処理できる別のレイヤーについて考えていました。

進行レベル ( )、ステータス、スローされた例外 ( を使用)を含む、Contextそれぞれに添付されたようなものを想像しましたが、エラーは停止後にのみスローされます。例外がスローされたときに中断したいと思います。 PluginBackgroundWorker.ReportProgressRunWorkerCompletedEventBackgroundWorker

また、アスペクト指向プログラミングが優れた方法になる可能性があると考えていました。ネットで調べてみると、Spring.NETのようなフレームワークが見つかりました。しかし、それが私の場合に適切かどうかはわかりません。

[更新] リクエストに応じて、デザインの詳細を以下に示します。

  • IPlugin インターフェイス: 呼び出されるAbstractEnvChecker:

抽象環境チェッカー

アプリケーションはリッチ クライアント アプリです。プラグインをコンパイルした後、生成されたプラグインDLLがロードされ、リストが単純な Windows フォームでユーザーに表示されます。ユーザーが起動するプラグインを選択すると、Plugin.DoWork()メソッドが呼び出されます。

ホストが選択したプラグインを起動する方法は次のとおりです。

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);
    }
}

AOPエラー処理レイヤーを追加する適切なソリューションはありますか?

4

2 に答える 2

3

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

于 2012-06-28T18:43:40.850 に答える
1

Spring.net は動的ウィービングを使用します。これは基本的に、実行時に Spring.net aop がメソッド呼び出しの周りに例外ハンドラーをラップできることを意味します。しかし、Spring.net aop には、インターセプターを配置するための継ぎ目が必要です。

プラグインを UI にロードする必要がある場合、ユーザーは (おそらく) ホストまたはインターフェイスをまったく通過しないメソッドを呼び出すことがIPluginでき、spring.net aop が例外をインターセプトしてラップすることが (不可能ではないにしても) 難しくなります。ハンドラー。

ホストが を呼び出すコンソール アプリケーションまたはサービスである場合、myPlugin.DoWork()Spring.net aop. もう少し詳細を提供していただければ (質問へのコメントを参照)、その方法をお見せできます。

Spring.net AOP を使用してプラグイン インスタンスをプロキシし、スローされた例外をキャッチしてホストに委任するインターセプターでラップする例を以下に示します。AOP なしでもこれを行うことができることに注意してください...それはあなた次第です。

using System;
using AopAlliance.Intercept;
using NUnit.Framework;
using Spring.Aop.Framework;

namespace Aop
{

    [TestFixture]
    public class SimpleProxyFactoryTests
    {
        [Test]
        public void Main()
        {
            var host = new Host();

            var mp = new SimplePlugin(); 
            var pf = new ProxyFactory(mp);
            pf.AddAdvice(new DelegateToHostExceptionHandlingAdvice(host));

            var proxy = (IPlugin)pf.GetProxy();

            proxy.DoWork();
        }
    }

    public interface IPlugin
    {
        void DoWork();
    }

    public class Host
    {
        public void HandleExceptionFromPlugin(Exception ex)
        {
            Console.WriteLine("Handling exception: {0}", ex.Message);
        }
    }

    public class SimplePlugin : IPlugin
    {
        public void DoWork()
        {
            Console.WriteLine("Doing it and throwing an exception ... ");

            throw new ApplicationException("Oops!");
        }
    }

    public class DelegateToHostExceptionHandlingAdvice : IMethodInterceptor 
    {
        private readonly Host _host;

        public DelegateToHostExceptionHandlingAdvice(Host host)
        {
            _host = host;
        }

        public object Invoke(IMethodInvocation invocation)
        {
            try
            {
                return invocation.Proceed();
            }
            catch (Exception ex)
            {
                 _host.HandleExceptionFromPlugin(ex);
                return null; 
            }
        }
    }
}

討論

aop フレームワークを活用して例外処理を行う方法をお見せできたと思います。Sebastian が彼の回答で言及しているように、Spring aopを例外ラッピングにのみ使用することは、やり過ぎと見なされる可能性があります-そして私は同意します; 彼のコード例の単純さと私のコード例の複雑さを比較してください。どちらかをチームの新しい開発者に説明することを想像してみてください。

Spring aop は、Spring IOC コンテナーと組み合わせて使用​​すると「輝き」始めます。

于 2012-06-28T14:11:58.933 に答える