Blog de Julien Corioland (MSP)

Quand les technologies .NET deviennent passion...

[.NET 4.0] Première application MEF : Recomposition du catalogue de module au Runtime

Toujours dans la découverte de MEF et suite aux conseils de Sébastien après la lecture de mon premier post sur le sujet, je souhaiterai apporter de nouvelles informations !

Jusque là, notre application est capable de charger automatiquement, au démarrage, les modules qui sont placés dans un répertoire ciblé. Dans ce post, je vais vous montrer comment faire en sorte que l’application soit réactive à l’ajout/suppression de modules au runtime !

Commençons tout d’abord par visionner ce à quoi nous souhaitons arriver :

Voyons à présent comment réaliser cela. Les modifications à apporter au code de l’article précédent ne sont pas énormes, cependant vous verrez dans les sources disponibles au bas de cette page que j’ai complètement externalisé le code MEF dans une classe “PluginsManager”.

Tout d’abord, vous devez autoriser votre instance de ExportCollection à être recomposée au runtime. Pour cela, vous devez définir la propriété “AllowRecomposition” de l’attribut “Import” à true :

[Import(typeof(IApplicationModule),AllowRecomposition=true)]
public ExportCollection<IApplicationModule> Modules { get; set; }

Le DirectoryCatalog utilisé pour récupérer les différents modules dans le répertoire “Modules” de l’application possède deux membres remarquables :

  • La méthode Refresh, qui va permettre de relire le contenu du répertoire associé et de rafraîchir la collection de modules.
  • L’évènement “Changed” qui sera levé lors d’un changement de cette même collection.

Commencez par vous abonner à l’événement :

this.directoryCatalog.Changed += 
    new EventHandler<ComposablePartCatalogChangedEventArgs>(directoryCatalog_Changed);

Dans cette méthode, j’ai tout simplement choisi de lancer une recomposition du CompositionContainer et de lever un événement pour notifier que la collection de modules a changé :

protected void OnModulesCollectionChanged()
{
    if (this.ModulesCollectionChanged != null)
    {
        this.ModulesCollectionChanged(this, EventArgs.Empty);
    }
}

private void directoryCatalog_Changed(object sender, ComposablePartCatalogChangedEventArgs e)
{
    this.compositionContainer.ComposeParts(this);
    OnModulesCollectionChanged();
}

Au niveau de mon formulaire principal, je suis abonné à l’événement “ModulesCollectionChanged” afin de regénérer le layout de celui-ci.

Il ne reste plus qu’à lancer la surveillance du répertoire Modules, pourquoi pas à l’aide d’un FileSystemWatcher et appeler la méthode “Refresh” du DirectoryCatalog lorsqu’un changement survient.

private void WatchModulesDirectory(object oDirectoryToWatch)
{
    string directoryToWatch = oDirectoryToWatch.ToString();
    if (Directory.Exists(directoryToWatch))
    {
        FileSystemWatcher watcher = new FileSystemWatcher(directoryToWatch, "*.dll");
        watcher.Created += new FileSystemEventHandler(ModulesDirectoryChanged);
        watcher.Changed += new FileSystemEventHandler(ModulesDirectoryChanged);
        watcher.Deleted += new FileSystemEventHandler(ModulesDirectoryChanged);

        watcher.EnableRaisingEvents = true;

        Thread.Sleep(Timeout.Infinite);
    }
}
ThreadPool.QueueUserWorkItem(
    new WaitCallback(WatchModulesDirectory), modulesDirectoryPath
);
private void ModulesDirectoryChanged(object sender, FileSystemEventArgs e)
{
    //délégué qui invoke RefreshModuleCollection car dans un thread différent
    OnModuleDirectoryChangedAction.Invoke();
}

private void RefreshModulesCollection()
{
    this.directoryCatalog.Refresh();
}

Le tour est joué, votre application sera réactive à l’ajout/suppression de modules lors de son exécution !

A bientôt Wink

Sources : TestMEF_2.zip (127.73 kb)

Posted: May 23 2009, 15:17 by julienc | Comments (1) RSS comment feed |
  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .NET 4.0 | CSharp | Général

Comments

geuk said:

Impressionnant !

# May 24 2009, 03:13

Add comment




biuquote
  • Comment
  • Preview
Loading

captcha

*