LES APPLICATIONS MODULAIRES : Plug-In, Add-In, Add-on (1ère partie)

Les applications que nous développons sont très souvent amenées à évoluer. Lorsque nous désirons ajouter de nouvelles fonctionnalités l’une des solutions est de recompiler l’application et de mettre la nouvelle version à la disposition des utilisateurs. Il leur faudrait donc désinstaller l’ancienne application afin d’installer la nouvelle. L’une des solutions à ce problème est de construire des applications modulaires, c’est-à-dire avec des fonctionnalités qui se rajoutent automatiquement sans avoir besoin de recompiler l’application. Il existe beaucoup d’application utilisant ce fonctionnement :

  • Internet Explorer
  • Visual Studio
  • Word
  • Etc…

Ce billet a pour objectif de vous apprendre à développer vos applications de façon modulaire.

Comment ça marche ?

Le fonctionnement est simple. Vous devez exposer les fonctionnalités de vos applications dans des fichiers dll. Ces dll seront vos plugins. Toute application prenant en charge les plugins doit être capable de :

  • Charger dynamiquement les plugins à son démarrage.
  • Vérifier que les plugins respectent leur contrat (nous y reviendrons).
  • Communiquer avec ces plugins.
  • S’assurer que ces plugins fonctionnent toujours même en cas d’évolution de l’application.

Certains points vous paraissent surement évidents mais ils sont tout de même importants.

Revenons sur le 2ème point :

  • Vérifier que les plugins respectent leur contrat.

En effet, la 1ère étape pour créer un plugin est de définir un contrat (ou modèle) c’est-à-dire la structure que doivent respecter les plugins afin de pouvoir communiquer avec votre application. Du point de vu de la programmation vous avez deux manières de définir ce modèle :

  1. Une classe abstraite
  2. Une interface

Alors classe ou interface ?

Nous n’allons pas nous mettre à faire une étude comparative en classe abstraite et interface. Toutefois sachez qu’en .NET une classe ne peut hériter que d’une seule classe mais peut implémenter plusieurs interfaces.

Nous utiliserons donc les interfaces afin de ne pas obliger les développeurs de plugins à hériter de notre contrat (contrat de plugin).

Etape 1 : Création d’une solution Visual Studio

Commençons par créer une solution pour nos différents projets.

  1. Dans Visual Studio, créer un nouveau projet basé sur le template Bibliothèque de classes et nommer le PluginContract.
  2. Nommer la solution PluginApp.

Etape 2 : Création du contrat

  1. Dans Visual Studio, ouvrez le projet nommé PluginContract.
  2. Dans l’explorateur de solution, supprimez la classe créée par défaut.
  3. Dans l’explorateur de solution, ajoutez une nouvelle interface au projet puis nommez-la : IPlugin.
  4. Insérez le code ci-dessous


    Nos plugins pourront donc faire deux choses : Do et Other.

Etape 3 : Création des plugins

Créons le 1er plugin :

  1. Ajoutez un nouveau projet basé sur le template Bibliothèque de classes à la solution et nommer le Plugin1.
  2. Ajoutez une référence au projet PluginContract.
  3. Sélectionnez la référence de projet et dans la fenêtre de propriété mettez Copie
    locale à false.
  4. Renommez la classe par défaut en Plugin1.
  5. Faites-la implémenter l’interface IPlugin.
  6. Insérer le code ci-dessous

Créons un autre plugin :

Répétez les étapes 1 à 6 en changeant Plugin1 par Plugin2.


Etape 4 : Création de l’application hôte

Les plus attentifs d’entre vous se souviendront de ceci :

Toute application prenant en charge les plugins doit être capable de :

  • Charger dynamiquement les plugins à son démarrage.

C’est ce que nous allons faire.

  1. Ajoutez un nouveau projet basé sur le template Application console à la solution et nommer le MyApp.
  2. Ajoutez une référence au projet PluginContract.
  3. Sélectionnez la référence de projet et dans la fenêtre de propriété mettez Copie
    locale à false.
  4. Dans l’explorateur de solution, ajouter une nouvelle classe au projet puis nommez-la : PluginLoader.

Insérer le code ci-dessous :

public static class PluginLoader
{
  public static ICollection<IPlugin> LoadPlugins(string path)
  {
    string[] dllFileNames = null;
    if (Directory.Exists(path))
    {
      dllFileNames = Directory.GetFiles(path, "*.dll");
      ICollection<Assembly> assemblies = new List<Assembly>(dllFileNames.Length);
      foreach (string dllFile in dllFileNames)
      {
        AssemblyName an = AssemblyName.GetAssemblyName(dllFile);
        Assembly assembly = Assembly.Load(an);
        assemblies.Add(assembly);
      }
      Type pluginType = typeof(IPlugin);
      ICollection<Type> pluginTypes = new List<Type>();
      foreach (Assembly assembly in assemblies)
      {
        if (assembly != null)
        {
          Type[] types = assembly.GetTypes();
          foreach (Type type in types)
          {
            if (type.IsInterface || type.IsAbstract)
            {
              continue;
            }
            else
            {
              if (type.GetInterface(pluginType.FullName) != null)
              {
                pluginTypes.Add(type);
              }
            }
          }
        }
      }
      ICollection<IPlugin> plugins = new List<IPlugin>(pluginTypes.Count);
      foreach (Type type in pluginTypes)
      {
        IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
        plugins.Add(plugin);
      }
      return plugins;
    }
    return null;
  }
}

  1. Dans la classe Program.cs ajoutez le code ci-dessous :

Etape 5 : Création d’un répertoire d’installation

Lorsque vous développez une application modulaire vous devez mettre tous vos plugins dans un dossier particulier qui se trouve généralement dans le dossier d’installation de votre application. Pour simuler ceci nous allons créer les dossiers suivants n’importe où sur notre disque :

MyApp
Plugins
PluginContract

Configuration des options de déploiement :

  1. Pour chacun des projets dans la solution, allez dans l’onglet Générer des propriétés du projet puis changez le chemin de sortie comme suit :
Projet Chemin
MyApp MyApp
Plugin1 MyApp\Plugins
Plugin2 MyApp\Plugins
PluginContract MyApp\PluginContract
  1. Ensuite générez la solution (F6)
  2. Dans l’explorateur de solution, définir MyApp comme projet de démarrage.
  3. Exécuter l’application (F5)

Si tout se déroule sans erreur vous obtiendrai cet écran :


Nous verrons dans un prochain billet une autre approche pour réaliser des applications modulaire. Cette nouvelle autre approche facilitera grandement le chargement dynamique des plugins…

En attendant j’espère que vous avez aimé ce billet.

Publicités

3 commentaires sur “LES APPLICATIONS MODULAIRES : Plug-In, Add-In, Add-on (1ère partie)

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s