Commençons tout d'abord par un petit rappel de l'interface utilisée par la classe AssemblyUpdater:

public interface IFileInstaller
{
    IObservable<Unit> Install(string filePath);
}

La manière dont on a utilisé jusque là les IObservable<Unit> était d'informer les observateurs de la fin de l'observable, étant donné que le type Unit ne transporte pas de données (c'est un void qui s'ignore). Le souci ici, c'est que si on suit cette logique, on informera la vue d'un changement uniquement à la fin de l'installation de chaque update. Ce qui n'est pas très pratique si vous voulez avoir la possibilité d'informer l'utilisateur qu'une installation est en cours. Mais ce n'est heureusement pas un problème du tout, puisqu'on pourra très bien, en utilisant Observable.Create<Unit>, appeler la fonction OnNext de l'observer avant de réellement exécuter la mise à jour.

De cette façon, on va commencer par informer la vue qu'une installation va débuter, ce qui va lui permettre par exemple d'afficher une progressbar avec la propriété IsIndeterminate définie à True.

Mais voyons sans plus attendre l'implémentation de notre interface:

public class FileInstaller : IFileInstaller
{
	private static IObservable<Unit> DoInstall(string filePath)
	{
		return Observable.Create<Unit>(...);
	}

	public IObservable<Unit> Install(string filePath)
	{
		return Observable.ToAsync(() => DoInstall(filePath).First())();
	}
}

Comme vous pouvez le constater, il est très simple d'exécuter une fonction en asynchrone: il suffit d'utiliser Observable.ToASync(), qui prend comme argument dans notre cas un paramètre de type Func<IObservable<Unit>> pour retourner un résultat de même type. Par défaut, ToAsync va exécuter le code contenu dans le Func passé en paramètre dans un nouveau thread (si on ne spécifie pas le paramètre IScheduler, celui-ci prend Scheduler.TaskPool comme valeur par défaut).

Vous noterez également l'appel à la méthode d'extension First() sur l'observable retourné par DoInstall(), ceci afin d'utiliser sa propriété bloquante pour ne quitter ToAsync que lorsque l'installation est terminée. (Vous aurez remarqué également la fin de ligne très lisible avec toutes ces parenthèses :x)

Et pour terminer, la définition de DoInstall, avec notamment l'appel à OnNext avant le lancement de la mise à jour:

private static IObservable<Unit> DoInstall(string filePath)
{
    return Observable.Create<Unit>(observer =>
            {
                using (Process process = new Process())
                {
                    try
                    {
                        observer.OnNext(new Unit());

                        process.StartInfo.FileName = filePath;
                        process.StartInfo.CreateNoWindow = true;
                                                       
                        process.Start();

                        process.WaitForExit();

                        int exitCode = process.ExitCode;

                        process.Close();

                        if (exitCode != 0)
                            observer.OnError(new UpdateExecutionException(Resources.Resources.FileInstallerPrematureExit));
                        else
                            observer.OnCompleted();
                    }
                    catch (Win32Exception e)
                    {
                        const int errorAccessDenied = 5;

                        observer.OnError(e.NativeErrorCode == errorAccessDenied
                                            ? new UpdateExecutionException(Resources.Resources.FileInstallerPermissions, Resources.Resources.AccessDeniedError)
                                            : new UpdateExecutionException(Resources.Resources.FileInstallerUnknownError, e));
                    }
                }

                return () => { };
            });
}

Rien de bien compliqué donc :)

Et voilà qui conclue de fort belle manière ma foi (je suis objectif si je veux) cette petite série d'articles autour de l'utilisation de Rx dans un contexte concret.

Soyez sûr en tout cas de retrouver encore d'autres articles autour de cette fantastique technologie (au moins 1 article est prévu pour les jours qui viennent)

A bientôt !!!