我的团队正在开发一个插件项目,其中主机应用程序协调插件工作(每个插件都有一个特定的功能,将在一个单独的线程上执行)。我正在编写Host应用程序并定义IPlugin接口;其他人会开发插件。
问题是:如何知道插件何时完成或抛出异常。我有一个解决方案是使用event和delegate让Plugins回调Host应用程序,但我认为这种方法并不是很好。因为如果开发Plugin人实现了我的IPlugin接口,却忘了编写引发事件代码。
在这种情况下,插件可以插入我的主机应用程序,但我的主机应用程序无法知道此插件何时完成或抛出异常或其他通信,这是非常糟糕的。
我的代码喜欢这个:
IPlugin.cs:
public delegate void OnFinishDelegate(IPlugin p, AMessageEventArgs e);
public delegate void OnExceptionDelegate(IPlugin p, AMessageEventArgs e);
public interface IPlugin
{
event OnFinishDelegate OnFinish;
event OnExceptionDelegate OnException;
void DoWork();
}
EventArgs的:
public class AMessageEventArgs:EventArgs
{
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
主机申请:
static void Main(string[] args)
{
// ...ignore load plugin code
//
IPlugin p = new Plugin();
// register event with IPlugin
p.OnFinish += new OnFinishDelegate(OnFinishHandler);
p.OnException += new OnExceptionDelegate(OnExceptionHandler);
// let plugin do its work on a subthread
Thread t = new Thread(p.DoWork);
t.Start();
// and then main continue do other work...
}
// if plugin throw exception, in the host application will
// handle this exception...
private static void OnExceptionHandler(IPlugin p, AMessageEventArgs e)
{
// in here will process exception of plugin...
}
// if plugin completed its work, it will use OnFinish event to
// notify to host application
private static void OnFinishHandler(IPlugin p,AMessageEventArgs e)
{
// in here will process completed work event
}
我希望插件代码如下:
public class Plugin:IPlugin
{
// use event to callback host application
public event OnFinishDelegate OnFinish;
public event OnExceptionDelegate OnException;
// Create an EventArgs
AMessageEventArgs e = new AMessageEventArgs();
public void DoWork()
{
try
{
// execute update data
UpdateData();
}
catch (Exception ex)
{
e.Message = ex.Message;
// if have any exception, Plugin will raise an event in host application
// but if developer forget write below three lines of code, my host application will
// out of control.
if (OnException!=null)
{
OnException(this,e);
}
}
// if have no exception, Plugin will use OnFinish event to talk to host application
// to know that this plugin completed its work
// but if developer forget write below three lines of code, my host application will
// out of control.
if (OnFinish!=null)
{
OnFinish(this,e);
}
}
如何解决此问题?
其他问题:我的IPlugin界面定义得很好吗?如果不好,你能否建议我改进这个界面。
谢谢!
答案 0 :(得分:3)
我不认为插件需要知道它们是在单独的线程中运行的。我只是:
interface IPlugin {
void DoWork();
}
然后主程序将处理捕获异常和所有线程,例如:
Thread t = new Thread(() => {
try {
plugin.DoWork();
}
catch (Exception ex) {
// handle exception or save it to handle in the main thread
}
});
t.Start();
答案 1 :(得分:2)
您已正确识别界面中event
模型的问题 - 当插件实现IPlugin
界面时,他们必须定义OnException
事件,但那里没有什么要求他们使用它。
使用单个IPlugin
方法定义DoWork
接口,并允许标准异常模式报告成功完成或错误状态。如果DoWork
方法正常返回,则插件已完成(不需要OnFinish
事件)。如果DoWork
抛出异常,您的主应用程序可以捕获异常并处理它(不需要OnException
事件。)
我建议查看Task Parallel Library来执行插件。它提供了比直接使用线程更多的控制,包括exception handling。
答案 2 :(得分:0)
我刚刚阅读了HeadFist Design模式并发现了一个解决方案:工厂方法
在我的情况下,我应该使用抽象类而不是接口(IPlugin)。在这个抽象类中,我定义了一个Operate()方法,它将结果(完成的结果或异常结果)报告给我的宿主应用程序。第二种方法是DoWork()方法,第三方程序员可以编写他的函数并且不关心OnComplete或OnException事件。
我的代码如下:
摘要课:
public delegate void OnFinishDelegate(APlugin p, AMessageEventArgs e);
public delegate void OnExceptionDelegate(APlugin p, AMessageEventArgs e);
public abstract class APlugin
{
public event OnFinishDelegate OnFinish;
public event OnExceptionDelegate OnException;
AMessageEventArgs e = new AMessageEventArgs();
public void Operate()
{
try
{
// implement plugin work
// we don't care how does the third party programmer write his Plugin program
DoWork();
// if DoWork() completed , it will raise an OnFinish event
// in my host application
e.Message = "Completed";
if (OnFinish != null)
{
OnFinish(this, e);
}
}
catch(Exception ex)
{
// if DoWork() throw exception, it will raise an OnException event
// in my host application
e.Message = ex.Message;
if (OnException!=null)
{
OnException(this,e);
}
}
}
// In here, the third party programmer will override this DoWork() method
private abstract void DoWork();
}

主机应用代码:
static void Main(string[] args)
{
// ...ignore load plugin code
//
APlugin p = new Plugin();
// register event with IPlugin
p.OnFinish += new OnFinishDelegate(OnFinishHandler);
p.OnException += new OnExceptionDelegate(OnExceptionHandler);
// let plugin do its work on a subthread
Thread t = new Thread(p.Operate);
t.Start();
// and then main continue do other work...
}
// if plugin throw exception, in the host application will
// handle this exception...
private static void OnExceptionHandler(APlugin p, AMessageEventArgs e)
{
// in here will process exception of plugin...
}
// if plugin completed its work, it will use OnFinish event to
// notify to host application
private static void OnFinishHandler(APlugin p, AMessageEventArgs e)
{
// in here will process completed work event
}

>
和插件代码(必须如下):
class Plugin:APlugin
{
public override void DoWork()
{
// in here, the third party programmer can write anything
// for example: update data in database
UpdateData();
}
private void UpdateData()
{
// do update data
}
}