基于插件架构的Windows服务

时间:2012-10-19 12:53:14

标签: c# windows-services

我正在构建基于插件架构的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()
        {
            ...
        }
    }

除了事件之外,everythig工作得很好。 这里发生错误

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.

1 个答案:

答案 0 :(得分:1)

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