Publié dimanche 3 février 2008 13:28 par Adrien Siffermann

[Silverlight] Créer une application modulaire (Partie 2)

Dans le précédent billet, nous avons vu comment créer un module en Silverlight qui dispense un objet Control, ainsi qu'un WebService qui permet de donner une liste de tous les modules disponibles côté serveur. Nous allons voir aujourd'hui comment, à partir de la liste des modules récupérée depuis le WebService, nous allons pouvoir les télécharger au chargement de la page, puis incorporer les Control que ces derniers dispensent dans le Canvas principal.

J'ai écrit une classe Modman qui s'occupe de la première partie. Il appelle le WebService pour récupérer les URI relatives, télécharge la DLL grâce au Downloader puis créé une instance de la classe qui implémente l'interface IModule avec Activator.CreateInstance. Toutes les instances des modules sont alors stockées dans une liste accessible en lecture.

    public class Modman

    {

        private List<IModule> _modules = new List<IModule>();

        private ModmanWS.Modman _ws = new ModmanWS.Modman();

        private List<ModuleAssembly> _modAssemblyList = new List<ModuleAssembly>();

 

        public event EventHandler OnAllModulesLoaded;

        public event EventHandler OnModuleDownloadFailed;

        public event EventHandler<ModuleErrorEventArgs> OnModuleLoadError;

 

        public List<IModule> ModulesInstances

        {

            get { return _modules; }

        }

 

        public void DownloadAndLoadAllModules()

        {

            string[][] modList = _ws.GetModulesList();

 

            foreach (var mod in modList)

            {

                ModuleAssembly assembly = new ModuleAssembly(mod[0], mod[1], new Uri(mod[2], UriKind.Relative));

                _modAssemblyList.Add(assembly);

 

                Downloader loader = new Downloader();

                loader.Completed += new EventHandler(onDownloadComplete);

                loader.DownloadFailed += new ErrorEventHandler(onDownloadFailed);

 

                loader.Open("GET", assembly.Url);

                loader.Send();

            }

        }

 

        private void onDownloadComplete(object sender, EventArgs e)

        {

            ModuleAssembly assemblyInfo = retrieveAssemblyDownloaded(sender as Downloader);

 

            if (assemblyInfo != null)

            {

                loadModule(assemblyInfo);

                _modAssemblyList.Remove(assemblyInfo);

                if (_modAssemblyList.Count == 0 && this.OnAllModulesLoaded != null)

                    this.OnAllModulesLoaded(this, new EventArgs());

            }

        }

 

        private void onDownloadFailed(object sender, EventArgs e)

        {

            if (this.OnModuleDownloadFailed != null)

                this.OnModuleDownloadFailed(this, new EventArgs());

        }

 

        private ModuleAssembly retrieveAssemblyDownloaded(Downloader loader)

        {

            ModuleAssembly assemblyInfo = null;

            foreach (ModuleAssembly assembly in _modAssemblyList)

            {

                if (assembly.Url == loader.Uri)

                {

                    assemblyInfo = assembly;

                    break;

                }

            }

            return assemblyInfo;

        }

 

        private void loadModule(ModuleAssembly assemblyInfo)

        {

            try

            {

                Assembly assembly = Assembly.Load(assemblyInfo.AssemblyName);

                foreach (Type type in assembly.GetTypes())

                {

                    if (type.GetInterface(typeof(IModule).FullName, false) != null)

                    {

                        IModule instance = (IModule)Activator.CreateInstance(type);

                        _modules.Add(instance);

                    }

                }

            }

            catch (Exception ex)

            {

                if (OnModuleLoadError != null)

                    OnModuleLoadError(this, new ModuleErrorEventArgs(ex));

            }

        }

    }

Notez que j'utilise un objet ModuleAssembly, qui ne me sert en fait qu'à stocker les informations d'un module que retourne le WebService.

On y est presque ! Dans le code de ma page principale Silverlight, je m'abonne aux évènements de Modman, pour pouvoir afficher l'état du chargement des modules dans mon Canvas, et lorsque tous les modules ont été chargés, je récupère la liste des instances de modules, et j'ajoute pour chacun d'entre eux le MainControl au Canvas.

    public partial class Page : Canvas

    {

        public void Page_Loaded(object o, EventArgs e)

        {

            InitializeComponent();

            Modman mm = new Modman();

 

            mm.OnAllModulesLoaded += new EventHandler(ModMan_OnAllModulesLoaded);

            mm.OnModuleDownloadFailed += new EventHandler(ModMan_OnModuleDownloadFailed);

            mm.OnModuleLoadError += new EventHandler<ModuleErrorEventArgs>(ModMan_OnModuleLoadError);

 

            mm.DownloadAndLoadAllModules();

        }

 

        void ModMan_OnModuleLoadError(object sender, ModuleErrorEventArgs e)

        {

            this.statusText.Text += e.Exception.Message;

        }

 

        void ModMan_OnModuleDownloadFailed(object sender, EventArgs e)

        {

            this.statusText.Text += "Cannot download module";

        }

 

        void ModMan_OnAllModulesLoaded(object sender, EventArgs e)

        {

            try

            {

                Modman moduleManager = sender as Modman;

                foreach (IModule module in moduleManager.ModulesInstances)

                {

                    Control ctrl = module.MainControl;

 

                    ctrl.SetValue<double>(Canvas.LeftProperty, 50);

                    ctrl.SetValue<double>(Canvas.TopProperty, 50);

                    ctrl.Visibility = Visibility.Visible;

 

                    this.Children.Add(ctrl);

                }

            }

            catch (Exception ex)

            {

                this.statusText.Text += ex.Message;

            }

        }

    }

Et voilà, nous avons une application Silverlight complètement modulaire ! Les modules sont libres de personnaliser le contrôle qu'ils veulent mettre à disposition, tandis que l'application centrale garde la main sur la disposition de ces derniers dans la Canvas principal. De plus, il suffit de modifier le WebService en filtrant la liste des modules qu'il retourne pour apporter une logique métier aux modules activés (selon l'utilisateur par exemple).

Adrien

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Classé sous

# re: [Silverlight] Créer une application modulaire (Partie 2) @ dimanche 3 février 2008 19:19

Très malin comme technique: bonne idée :)

Thomas LEBRUN

# re: [Silverlight] Créer une application modulaire (Partie 2) @ lundi 4 février 2008 10:17

Vraiment très bien, merci

pc152


Les 10 derniers blogs postés

- Les actualités de la semaine sur c2i.fr (14 mai - 20 mai) par Richard Clark le il y a 3 heures et 46 minutes

- Reactive Extensions : Consommer des services avec Rx Partie 3, les pièges à éviter par Léonard Labat le il y a 12 heures et 51 minutes

- SharePoint Blog Site, problème d’archives par Le Blog (Vert) d'Arnaud JUND le il y a 23 heures et 27 minutes

- Soirée ALT.NET Mai - 3 présentations par #Rui le 05-18-2012, 11:59

- [ #SharePoint 2010][ #SQLServer 2012] AlwaysOn pour SharePoint (2/4) : Configuration (2e partie)… par Le blog de Patrick [MVP SharePoint] le 05-18-2012, 11:31

- Team Foundation Server 11: tous les trésors cachés du site d’équipe par Philess le 05-16-2012, 19:01

- [PowerShell 3] Télécharger et installer la documentation en ligne par Blog de SPBrouillet (Pierrick BROUILLET) le 05-16-2012, 17:36

- [#SharePoint 2010][#SQLServer 2012] AlwaysOn pour SharePoint (1/4) : Configuration (1ère partie)… par Le blog de Patrick [MVP SharePoint] le 05-16-2012, 12:10

- Job Day @MIC Brussels - .Net Developers on Mobile applications par Le Blog (Vert) d'Arnaud JUND le 05-15-2012, 20:26

- [SharePoint 2010] – SharePoint 2010, Windows (Server) 8 et des erreurs IIS sont dans une VM… par Blog de SPBrouillet (Pierrick BROUILLET) le 05-14-2012, 12:10