I am building a windows service based on plugin architecture and I run into some problem.
The problem is I want plugin to fire event on the main application. Here is some code.
These are delegates
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);
}
This is interface
public interface IPluginInterface : IDisposable
{
string Identifier{ get; }
void Run();
void Dispose();
event ErrorHandler OnError;
event CompletedHandler OnCompleted;
event ProgressReportHandler OnProgress;
}
This is base class I want all plugins to inherit from
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;
}
This is plugin
public class CurrencyRatesPlugin : BasePlugin
{
public CurrencyRatesPlugin()
{
_identifier = "CurrencyRatesPlugin";
}
public override void Run()
{
try
{
ReportProgress("bla", 0);
}
catch (Exception e)
{
ReportError("bla");
}
}
}
And this is my windows service code
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()
{
...
}
}
And everythig is working fine except the events.
The error occurs here
this.pluginInterface.OnProgress += ProcessProgressReportHandler;
And the error message is
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.
I`ve added IHost interface and Initialize methods in plugin interface. When loading plugin in host application I call Initialize method of that plugin and pass Host to it. After this I have ability to call host methods from plugin.