Développer une application Windows en .NET de façon modulaire18/08/2003 niveau : Intermédiaire Vos applications doivent tout le temps évoluer, nécessitent de nouvelles fonctionnalités : la solution est de développer de façon modulaire afin que vos fonctionnalités se rajoutent automatiquement sans avoir à recompiler votre application à chaque fois. 1. Introduction 2. Développer une application avec plugin 2.1. L'interface 2.2. Le plugin 2.3. Développement de l'application principale 3. Conclusion 1. Introduction
Cet article vous permettra de voir comment développer des applications de
façon modulaire. Vous verrez comment faire pour intégrer une nouvelle fonctionnalité
sans tout recompiler mais juste en mettant la DLL dans le répertoire de votre
application. Pour cela nous utiliserons une interface pour donner un modèle à notre plugin. Ensuite nous développerons un plugin qui s'intègrera automatiquement dans l'application. Dans un premier temps nous verrons la notion d'interface et quelle est son utilité. Ensuite nous verrons comment réaliser un plugin à partir d'une interface. Pour terminer, nous verrons comment les intégrer dans votre application. 2. Développer une application avec plugin 2.1. L'interface
Afin de réaliser vos plugins vous devez IMPERATIVEMENT définir un modèle de
plugin. Sur le plan de la programmation, un modèle peut être défini soit
par une classe abstraite, soit plus généralement par une interface. En .NET une classe ne peut hériter que d'une SEULE autre classe mais de plusieurs interfaces. Il est donc fortement conseillé d'utiliser des interfaces. De cette manière, vos plugins pourront répondre à plusieurs modèles. Voici un exemple d'interface : Imports System Imports System.Windows.Forms Namespace PluginApp public interface IPlugin Function Traitement() As String Function VisualComponent() As System.Windows.Forms.UserControl
La fonction Traitement de vos plugins devra répondre au modèle et donc
retourner une chaîne de caractères. La fonction VisualComponent permettra de récupérer le composant visuel de vos plugins afin de l'intégrer dans votre application. L'interface est un projet à part entière : vous devez simplement développer une DLL qui contient uniquement votre interface. 2.2. Le plugin
La réalisation d'un plugin demande quelques règles. En effet pour
charger un plugin vous devez connaître le nom de l'espace de nom et
de la classe de votre plugin. Nous allons donc utiliser la règle
suivante pour l'exemple. Le plugin aura comme espace de nom
PluginApp et le nom de la classe sera PluginClass.
Imports System Imports System.ComponentModel Imports System.Drawing Imports System.Data Imports System.Windows.Forms Namespace PluginApp ' Classe du plugin respectant le modèle : hérite de IPlugin Public Class PluginClass Inherits System.Windows.Forms.UserControl Implements IPlugin 'ToDo: Add Implements Clauses for implementation methods of these interface(s) Private components As System.ComponentModel.Container = Nothing Private lbl As System.Windows.Forms.Label ' Constructeur : Initilialise la partie visuelle du composant Public Sub New () InitializeComponent() End Sub 'New ' Destructeur Protected Overrides Sub Dispose(ByVal disposing As Boolean ) If disposing Then If Not (components Is Nothing ) Then components.Dispose() End If End If MyBase .Dispose(disposing) End Sub 'Dispose ' Positionnement des composants visuels sur le contrôle représentant le plugin Private Sub InitializeComponent() Me .lbl = New System.Windows.Forms.Label() Me .SuspendLayout() Me .lbl.Location = New System.Drawing.Point(16, 8) Me .lbl.Name = "lbl" Me .lbl.Size = New System.Drawing.Size(64, 24) Me .lbl.TabIndex = 0 Me .lbl.Text = "Plugin 1" Me .Controls.Add(lbl) Me .Name = "UserControlPlugin1" Me .Size = New System.Drawing.Size(184, 96) Me .ResumeLayout(False ) End Sub 'InitializeComponent ' Fonction de traitement ' Dans cet exemple elle retourne juste un descriptif Public Function Traitement() As String Return "Le traitement du plugin 1" End Function 'Traitement ' Permet de récupérer le contrôle utilisateur qui est la classe d'où ' le returnthis. Public Function VisualComponent() As System.Windows.Forms.UserControl Return Me End Function 'VisualComponent End Class 'PluginClass End Namespace 'PluginApp
Comme vous pouvez le constater, la classe hérite de System.Windows.Forms.UserControl
ce qui signifie que le plugin est un composant visuel. Elle hérite
aussi de l'interface IPlugin que nous avons vu au paragraphe
précédent. N'oubliez pas de rajouter Le plugin est extrêmement simple : il retourne "Le traitement du plugin 1" lors de l'appel de la fonction Traitement, et le composant visuel lors de l'appel de la fonction VisualComponent. Ce composant contient un label avec comme texte "Plugin 1". Si vous souhaitez développer d'autres plugins vous devez OBLIGATOIREMENT faire hériter votre composant de l'interface IPlugin. De plus votre composant doit implémenter les fonctions Traitement et VisualComponent. Rien ne vous empêche de développer d'autres fonctions privées, liées au fonctionnement de votre composant. C'est ainsi que vous pourrez développer des fonctionnalités supplémentaires à votre application. Votre plugin est entièrement autonome hormis le fait qu'il doit intégrer une application. Pour cela votre plugin doit être développé sous forme de DLL. Pour la compilation vous devez rajouter la DLL de l'interface en tant que référence. 2.3. Développement de l'application principale
La dernière phase est celle du développement de l'application
principale. Pour notre exemple nous allons intégrer le plugin de façon
très simple. Un onglet qui contiendra votre plugin visuel,
sera créé dynamiquement dans le TabControl du formulaire. De plus,
la fonction Traitement sera appelée au chargement du formulaire.
Imports System Imports System.Drawing Imports System.Collections Imports System.ComponentModel Imports System.Windows.Forms Imports System.Data Namespace PluginApp ' Fenêtre principale Public Class frmMain Inherits System.Windows.Forms.Form Private components As System.ComponentModel.Container = Nothing Private tabControl As System.Windows.Forms.TabControl Public Sub New () InitializeComponent() ' Création d'une instance du plugin dans le domaine principal ' La fonction CreateInstanceFromAndUnWrap retourne un objet de type object Dim obj As Object obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap("Plugin1.dll", "PluginApp.PluginClass") ' Execution de la fonction de traitement MessageBox.Show(("Chargement de " + CType (obj, IPlugin).Traitement())) ' Rajout d'un tabPage avec le composant visuel du plugin ' Rajout d'un onglet ayant comme titre "Ma page" Dim tp As New TabPage("Ma page") ' Intégration du contrôle utilisateur dans le tabPage ' obj étant de type object, le cast est nécessaire pour pouvoir ' appeler la fonction VisualComponent de l'objet tp.Controls.Add(CType (obj, IPlugin).VisualComponent()) ' Ajout du tabPage au tabControl général tabControl.TabPages.Add(tp) End Sub 'New Protected Overrides Sub Dispose(disposing As Boolean ) If disposing Then If Not (components Is Nothing ) Then components.Dispose() End If End If MyBase .Dispose(disposing) End Sub 'Dispose ' Positionnement des composants visuels sur le formulairen Private Sub InitializeComponent() Me .tabControl = New System.Windows.Forms.TabControl() Me .SuspendLayout() Me .tabControl.Location = New System.Drawing.Point(16, 16) Me .tabControl.Name = "tabControl" Me .tabControl.SelectedIndex = 0 Me .tabControl.Size = New System.Drawing.Size(488, 232) Me .tabControl.TabIndex = 0 Me .AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me .ClientSize = New System.Drawing.Size(520, 269) Me .Controls.Add(tabControl) Me .Name = "frmMain" Me .Text = "Application Principale" Me .ResumeLayout(False ) End Sub 'InitializeComponent ' Point d'entrée du programme Shared <STAThread()> Sub Main() Application.Run(New frmMain()) End Sub 'Main End Class 'frmMain End Namespace 'PluginApp
Dans le constructeur une phase est importante : celle de la création
d'une instance du plugin.
Dim obj As Object
obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap("Plugin1.dll", "PluginApp.PluginClass")
Voici pourquoi dans les chapitres au dessus, je disais que vous deviez
connaître le namespace et le nom de la classe de votre plugin. La fonction
CreateInstanceFromAndUnWrap permet de créer une instance de la classe
donnée en second paramètre de la DLL spécifiée en premier paramètre. Dans le cas d'une application de production, le plus simple est de créer un répertoire "plugins" et d'y copier tous vos plugins. Ainsi il vous reste à développer une fonction qui liste les dll du répertoire et qui les charge. Si vous regardez dans la documentation MSDN vous constaterez que cette fonction retourne un objet de type object. Il faut donc le "caster" pour pouvoir utiliser les fonctions du plugin. 3. Conclusion
Grâce à un développement de ce type vous pouvez rajouter des
fonctionnalités facilement à votre application. Le tout est de le
prévoir au début du développement. Après vous pouvez le gérer de la façon
qui vous plait le plus : par des onglets comme dans l'exemple,
par des menus ou autres moyens.
Ce document peut être diffusé, amélioré, reformaté à souhait mais DOIT
IMPERATIVEMENT contenir la source du document (http://www.developpez.com).
|