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