编写、加载和存取插件程序(Plug-Ins)
2006-07-22 22:58:24 来源:WEB开发网BOOL CMyApp::InitInstance()
{
...
m_plugins.LoadAll(__typeof(ITextPlugin));
}
此处 m_plug-ins 为 CPluginMgr 的一个实例。构造函数的参数为一个子目录名(默认值是 “Plugins”);LoadAll 搜索该文件夹查找程序集,在该程序集中包含的类实现了所请求的接口。当它找到这样一个程序集,CPluginMgr 便创建一个该类的实例并将它添加到一个列表中(STL vector)。下面是关键代码段:
for (/* each type in assembly*/) {
if (iface->IsAssignableFrom(type)) {
{Object* obj = Activator::CreateInstance(type);
m_objects.push_back(obj);
count++;
}
}
换句话说,如果类型(type)可被赋值给 ITextPlugin,CPluginMgr 则创建一个实例并将其添加到数组。因为 CPluginMgr 是一个本机类,它无法直接保存托管对象,所以数组 m_objects 实际上是一个 gcroot<Object* > 类型的数组。如果你在 Visual C++ 2005 中使用新的 C++ 语法,可用 Object^ 替代。注意 CPluginMgr 是一个通用类,支持任何你设计的接口。只要实例化并调用 LoadAll 即可,并且你最终要用插件对象数组。CPluginMgr 报告它在 TRACE 流中找到的插件。如果你有多个接口,那么你可能得为每个接口使用单独的 CPluginMgr 实例,以便保持插件之间的隔离。
在性能上,CLR 团队的 Joel Pobar 在 MSDN 杂志 2005 年7月刊里写了一篇令人恐怖的文章(Reflection: Dodge Common Performance Pitfalls to Craft Speedy Applications),在这篇文章中,他讨论了使用反射的最佳实践。他建议利用程序集层面的属性来具体说明程序集中哪个类型实现了插件接口。这样便允许插件管理器快速查找并实例化插件,而不是非得循环查找程序集中的每种类型,如果类型太多,那将是个昂贵的操作。如果你发现本期专栏里的代码在加载你自己的插件时性能很糟的话,你应该考虑改用 Joel 推荐的方法。但是对于一般的情况,这个代码足以胜任。
更多精彩
赞助商链接