1

我正在构建基于插件架构的 Windows 服务,但遇到了一些问题。问题是我希望插件在主应用程序上触发事件。这是一些代码。

这些是代表

namespace eTreasury.SchedulerInterface
{
    public enum Severity
    {
        Message,
        Warning,
        Error
    }

    public delegate void ErrorHandler(string message, Severity errorSeverity);
    public delegate void CompletedHandler(string message);
    public delegate void ProgressReportHandler(string message, int percentCompleted);
}

这是界面

public interface IPluginInterface : IDisposable
    {
        string Identifier{ get; }

        void Run();
        void Dispose();

        event ErrorHandler OnError;
        event CompletedHandler OnCompleted;
        event ProgressReportHandler OnProgress;
    }

这是我希望所有插件继承的基类

public abstract class BasePlugin : MarshalByRefObject, IPluginInterface
{
    protected string _identifier;
    public string Identifier
    {
        get { return _identifier; }
    }

    public abstract void Run();

    protected void ReportError(string message, Severity errorSeverity)
    {
        if (OnError != null)
            OnError(message, errorSeverity);
    }
    protected void ReportProgress(string message, int percentCompleted)
    {
        if (OnProgress != null)
            OnProgress(message, percentCompleted);
    }
    protected void ReportProgress(string message)
    {
        ReportProgress(message, 0);
    }
    protected void ReportCompleted(string message)
    {
        if (OnCompleted != null)
            OnCompleted(message);
    }

    public void Dispose()
    {
        OnError = null;
        OnCompleted = null;
        OnProgress = null;
        _identifier = null;
    }

    public event ErrorHandler OnError;
    public event CompletedHandler OnCompleted;
    public event ProgressReportHandler OnProgress;
}

这是插件

public class CurrencyRatesPlugin : BasePlugin
{
    public CurrencyRatesPlugin()
    {
        _identifier = "CurrencyRatesPlugin";
    }

    public override void Run()
    {
        try
        {
           ReportProgress("bla", 0);
        }
        catch (Exception e)
        {
            ReportError("bla");
        }
    }
}

这是我的 Windows 服务代码

public partial class CurrencyRatesPluginService : ServiceBase
    {
        AppDomain appDomain;
        IPluginInterface pluginInterface;
        System.Timers.Timer Timer = null;

        public CurrencyRatesPluginService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
           try
            {
                this.appDomain = CreateAppDomain();
                this.pluginInterface = (IPluginInterface)appDomain.CreateInstanceFrom("C:\\eTreasuryScheduler\\Plugins\\eTreasury.CurrencyRatesPlugin.dll", "eTreasury.Plugins.CurrencyRatesPlugin.CurrencyRatesPlugin").Unwrap();

                PluginSection section = (PluginSection)ConfigurationManager.GetSection("PluginSectionGroup/PluginSection");
                if (section == null)
                {
                    EventLogManager.LogError("bla");
                }
                else
                {
                    Timer = new System.Timers.Timer();
                    Timer.Enabled = false;
                    Timer.Interval = section.PluginItems[0].Interval;
                    Timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
                    Timer.Start();
                }
            }
            catch(Exception ex)
            {
                EventLogManager.LogError(String.Format("{0}...{1}", ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message));
            }
        }

        protected override void OnStop()
        {
            Timer.Stop();
            this.pluginInterface.Dispose();
            AppDomain.Unload(this.appDomain);
        }

        void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Process();
        }

        void Process()
        {
            try
            {
                this.pluginInterface.OnProgress += ProcessProgressReportHandler;
                this.pluginInterface.OnCompleted += ProcessCompletedHandler;

                pluginInterface.Run();

                this.pluginInterface.OnProgress -= ProcessProgressReportHandler;
                this.pluginInterface.OnCompleted -= ProcessCompletedHandler;
            }
            catch (Exception ex)
            {
                EventLogManager.LogError(String.Format("{0}...{1}", ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message));
            }
        }

        private void ProcessProgressReportHandler(string message, int percentCompleted)
        {
            EventLogManager.LogInformation(message);
        }

        private void ProcessCompletedHandler(string message)
        {
            EventLogManager.LogInformation(message);
        }

        AppDomain CreateAppDomain()
        {
            ...
        }
    }

除了事件之外,一切都运行良好。错误发生在这里

this.pluginInterface.OnProgress += ProcessProgressReportHandler;

错误信息是

Exception has been thrown by the target of an invocation....Could not load file or assembly 'eTreasury.SchedulerService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
4

1 回答 1

1

我在插件接口中添加了 IHost 接口和 Initialize 方法。在主机应用程序中加载插件时,我调用该插件的 Initialize 方法并将 Host 传递给它。在此之后,我可以从插件调用主机方法。

于 2012-10-22T09:25:26.270 回答