【发布时间】:2010-03-25 13:36:09
【问题描述】:
我正在使用基于 Eclipse(可能还有其他)扩展点模型的动态加载共享库开发插件框架。所有插件共享相似的属性(名称、id、版本等),理论上每个插件都可以满足任何扩展点。实际的插件(即 Dll)处理由另一个库管理,我所做的只是管理应用程序的接口集合。
我一开始使用enum PluginType 来区分不同的接口,但我很快意识到使用模板函数可以使代码更简洁,并将繁琐的工作留给编译器,而不是强迫我使用大量switch {...} 声明。
唯一的问题是我需要为类成员指定类似的功能 - 最明显的例子是提供特定接口的默认插件。 Settings 类处理所有设置,包括接口的默认插件。
即Skin newSkin = settings.GetDefault<ISkin>();
如何将默认的ISkin 存储在容器中,而不使用其他识别接口的方法?
正如我上面提到的,我目前使用std::map<PluginType, IPlugin> Settings::defaults 成员来实现这一点(其中IPlugin 是所有插件派生自的抽象基类。然后我可以在需要时将dynamic_cast 到所需的接口,但这对我来说真的闻起来很糟糕,而且我认为弊大于利。
欢迎任何提示
编辑:这是当前使用默认插件的示例
typedef boost::shared_ptr<ISkin> Skin;
typedef boost::shared_ptr<IPlugin> Plugin;
enum PluginType
{
skin,
...,
...
}
class Settings
{
public:
void SetDefault(const PluginType type, boost::shared_ptr<IPlugin> plugin) {
m_default[type] = plugin;
}
boost::shared_ptr<IPlugin> GetDefault(const PluginType type) {
return m_default[type];
}
private:
std::map<PluginType, boost::shared_ptr<IPlugin> m_default;
};
SkinManager::Initialize()
{
Plugin thedefault = g_settings.GetDefault(skinplugin);
Skin defaultskin = boost::dynamic_pointer_cast<ISkin>(theskin);
defaultskin->Initialize();
}
我更愿意将 getdefault 调用如下,并自动转换为派生类。但是,我需要专门针对每种课程类型。
template<>
Skin Settings::GetDefault<ISkin>()
{
return boost::dynamic_pointer_cast<ISkin>(m_default(skin));
}
【问题讨论】:
-
您能否发布一些示例代码,说明如何使用默认值?我很难想象你在说什么。
-
如果
IPlugin是一个抽象类,您需要在地图中存储指针(无论如何您都需要这样做,否则会遇到切片问题)。 -
嗨 Kristo,添加了更多示例
-
抱歉 James 我应该指定我正在存储 shared_ptr(IPlugin)。我正在使用 boost::shared_ptrs 来避免挂起指向已卸载 Dll 的指针。