Je travaille sur un framework de plugin utilisant des bibliothèques partagées dynamiques chargées basées sur le modèle de point d'extension d'Eclipse (et probablement d'autres). Tous les plugins partagent des propriétés similaires (nom, identifiant, version, etc.) et chaque plugin pourrait en théorie satisfaire n'importe quel point d'extension. La gestion du plugin (ie Dll) est gérée par une autre bibliothèque, tout ce que je fais c'est gérer des collections d'interfaces pour l'application.éviter d'être en tant qu'identificateurs d'interface C++ OOP
J'ai commencé par utiliser un enum PluginType
pour distinguer les différentes interfaces, mais j'ai rapidement réalisé que l'utilisation de fonctions de template rendait le code beaucoup plus propre et laissait le travail au compilateur, plutôt que de me forcer à utiliser déclarations.
Le seul problème est lorsque j'ai besoin de spécifier une fonctionnalité similaire pour les membres de la classe - l'exemple le plus évident est le plugin par défaut qui fournit une interface particulière. Une classe Settings
gère tous les paramètres, y compris le plugin par défaut pour une interface.
-à-dire Skin newSkin = settings.GetDefault<ISkin>();
Comment stocker la valeur par défaut ISkin
dans un conteneur sans avoir recours à d'autres moyens d'identification de l'interface?
Comme je l'ai mentionné ci-dessus, j'utilise actuellement membre std::map<PluginType, IPlugin> Settings::defaults
pour y parvenir (où IPlugin
est une classe de base abstraite que tous les plug-ins dérivent. Je peux alors dynamic_cast
à l'interface désirée lorsque cela est nécessaire, mais cela sent vraiment de mauvaise conception pour moi et introduit plus de mal que de bien, je pense que
accueillerait favorablement des conseils
modifier. voici un exemple de l'utilisation actuelle des plug-ins par défaut
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();
}
J'appellerais plutôt getdefault comme suit, avec un cast automatique vers la classe dérivée. Cependant, je dois me spécialiser pour chaque type de classe.
template<>
Skin Settings::GetDefault<ISkin>()
{
return boost::dynamic_pointer_cast<ISkin>(m_default(skin));
}
Pouvez-vous poster un exemple de code de la façon dont on pourrait utiliser les valeurs par défaut? J'ai du mal à imaginer ce dont tu parles. –
Si 'IPlugin' est une classe abstraite, vous devrez stocker des pointeurs dans votre map (vous aurez besoin de le faire de toute façon, sinon vous aurez des problèmes de tranchage). –
salut Kristo, ont ajouté plus d'un exemple – AlasdairC