Construire des applications «Extensibles»



Documents pareils
Le hub d entreprise est une application de déploiement des applications mais aussi un outil de communication

Alfstore workflow framework Spécification technique

Tutoriel: Création d'un Web service en C++ avec WebContentC++Framework

Création d objet imbriqué sous PowerShell.

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Projet de programmation (IK3) : TP n 1 Correction

Programmer en JAVA. par Tama

SYNC FRAMEWORK AVEC SQLITE POUR APPLICATIONS WINDOWS STORE (WINRT) ET WINDOWS PHONE 8

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Héritage presque multiple en Java (1/2)

Programme Compte bancaire (code)

Construire une application marketing Facebook sur la plateforme Windows Azure

Serveur d'application Client HTML/JS. Apache Thrift Bootcamp

Programmation MacOSX / ios

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Auto-évaluation Programmation en Java

TP1 : Initiation à Java et Eclipse

Formation, Audit, Conseil, Développement, UX WinRT Silverlight WPF Android Windows Phone

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

Rafraichissement conditionné d'une page en.net

Programmation en Java IUT GEII (MC-II1) 1

Plateforme PAYZEN. Définition de Web-services

Classes et Objets en Ocaml.

Design patterns. Design patterns - définition. Design patterns - avantages

WEBSERVICES. Michael Fortier. Master Informatique 2ème année. A308, Université de Paris 13

REMBO Version 2.0. Mathrice 2004 DESCRIPTION MISE EN OEUVRE CONCLUSION.

Projet Android (LI260) Cours 2

OpenPaaS Le réseau social d'entreprise

Tp 1 correction. Structures de données (IF2)

Bases Java - Eclipse / Netbeans

Hébergement et configuration de services WCF. Version 1.0

Package Java.util Classe générique

Développement d un logiciel de messagerie instantanée avec Dotnet (version simplifiée)

Corrigé des exercices sur les références

Composants Logiciels. Le modèle de composant de CORBA. Plan

Le MSMQ. Version 1.0. Pierre-Franck Chauvet

Une introduction à la technologie EJB (2/3)

Apache Camel. Entreprise Integration Patterns. Raphaël Delaporte BreizhJUG

Une introduction à Java

Création d un service web avec NetBeans 5.5 et SJAS 9

Interfaces graphiques avec l API Swing

.NET - Classe de Log

Objets et Programmation. origine des langages orientés-objet

Développement Logiciel

Déploiement et monitoring

Définition des Webservices Ordre de paiement par . Version 1.0

Chapitre 10. Les interfaces Comparable et Comparator 1

Un ordonnanceur stupide

A DESTINATION DES SERVICES TIERS. Editeurs d applications et ressources pédagogiques connectées à l ENT

[APPLICATON REPARTIE DE VENTE AUX ENCHERES]

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

WebParts. Version 1.0

as Architecture des Systèmes d Information

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

TD/TP PAC - Programmation n 3

ASP.NET 2.0, C#, Spring.Net et NHibernate

JADE : Java Agent DEvelopment framework. Laboratoire IBISC & Départ. GEII Université & IUT d Evry nadia.abchiche@ibisc.univ-evry.

Introduction à la programmation concurrente

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Programmation Réseau. Sécurité Java. UFR Informatique jeudi 4 avril 13

Langage Java. Classe de première SI

La base de données XML exist. A. Belaïd

Chapitre VI- La validation de la composition.

Urbanisation des SI Conduite du changement IT 20/03/09. Patrick CHAMBET

Plan du cours. Historique du langage Nouveautés de Java 7

Flex. Lire les données de manière contrôlée. Programmation Flex 4 Aurélien VANNIEUWENHUYZE

Programmation par les Objets en Java

Paginer les données côté serveur, mettre en cache côté client

Tutoriel d installation de Hibernate avec Eclipse

Programmation Par Objets

27/11/12 Nature. SDK Python et Java pour le développement de services ACCORD Module(s)

Gestion du cache dans les applications ASP.NET

Page 1 sur 5 TP3. Thèmes du TP : l la classe Object. l Vector<T> l tutorial Interfaces. l Stack<T>

7 Développement d une application de MapReduce

Open Source Job Scheduler. Installation(s)

Rapport de Mini-Projet en ArcGIS Engine

INITIATION AU LANGAGE JAVA

Traduction des Langages : Le Compilateur Micro Java

Types d applications pour la persistance. Outils de développement. Base de données préexistante? 3 modèles. Variantes avec passerelles

Java Aspect Components (JAC)

Automatisation de l administration système

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

PROJET AZURE (par Florent Picard, A2011)

TD/TP PAC - Programmation n 3

1. Installation d'un serveur d'application JBoss:

Bases de données et fournisseurs de contenu

Utilisation de JAVA coté Application serveur couplé avec Oracle Forms Hafed Benteftifa Novembre 2008

Premiers Pas en Programmation Objet : les Classes et les Objets

Threads. Threads. USTL routier 1

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Développement mobile MIDP 2.0 Mobile 3D Graphics API (M3G) JSR 184. Frédéric BERTIN

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Les processus métiers : concepts, modèles et systèmes

Chapitre 1 Windows Server

Supervision et infrastructure - Accès aux applications JAVA. Document FAQ. Page: 1 / 9 Dernière mise à jour: 15/04/12 16:14

Transcription:

Construire des applications «Extensibles» Extensibilité / Patterns : Builder Factory Provider Module Pipeline Etc. IoC Containers MEF / System.ComponentModel.Composition + interfaces, abstraction Chaque composant doit avoir un contrat des fonctionnalités à remplir, un couplage faible et doit pouvoir être remplacé facilement sans devoir toucher au reste du code. Exemple : un cache a pour contrats : enregistrer des valeurs et les restituer, après peu importe la manière dont cela est fait à l intérieur de la classe, il faut pouvoir changer par un autre cache qui remplira ces fonctionnalités. 1. Pattern Provider Ajouter une référence à System.Configuration L intérêt du Pattern Provider est de permettre de changer les types à charger simplement depuis le fichier de configuration.il est possible ainsi de créer ses propres implémentations et les charger sans toucher au code source de base.

App.config <?xml version="1.0" encoding="utf-8"?> <configuration> <configsections> <section name="onesection" type="configurationdemo.onesectionconfigurationsection,configurationdemo"/> </configsections> <onesection> <!--type pointe sur le type à créer--> <mailer name="defaultmailer" type="configurationdemo.mailer,configurationdemo" email="xx@xx.fr" smtp="xxx.gmail.com"/> </onesection> </configuration> Section contenant une propriété pour chaque élément. // core configuration public class OneSectionConfigurationSection : ConfigurationSection [ConfigurationProperty("mailer", IsRequired = true)] public MailerElement Mailer get return (MailerElement)base["mailer"]; set base["mailer"] = value;

Eléments avec une propriété pour chaque attribut. // core configuration public class MailerElement : ConfigurationElement [ConfigurationProperty("name", IsRequired = true, IsKey = true)] public string Name get return (string)base["name"]; set base["name"] = value; [ConfigurationProperty("type", IsRequired = true)] public string Type get return (string)base["type"]; set base["type"] = value; [ConfigurationProperty("email", IsRequired = true)] public string Email get return (string)base["email"]; set base["email"] = value; [ConfigurationProperty("smtp", IsRequired = true)] public string Smtp get return (string)base["smtp"]; set base["smtp"] = value; (Charger la section) var config = ConfigurationManager.GetSection("oneSection") as OneSectionConfigurationSection; ConfigurationFactory // core contracts public interface IConfigurationFactory IMailer GetMailer(); // get other elements... // core public class ConfigurationFactory : IConfigurationFactory private IMailer _Mailer; public ConfigurationFactory() var config = ConfigurationManager.GetSection("oneSection") as OneSectionConfigurationSection; if (config!= null) // Création de l instance du type donné dans le fichier de config

IMailer mailer = Activator.CreateInstance(Type.GetType(config.Mailer.Type)) as IMailer; // chargement des propriétés du type créé mailer.email = config.mailer.email; mailer.smtp = config.mailer.smtp; _Mailer = mailer; public IMailer GetMailer() // retourne l instance créée return _Mailer; Manager // core contracts public interface IManager void DoSomething(); // core public class OneManager : IManager private IMailer _Mailer; public OneManager(IConfigurationFactory configurationfactory) // load providers _Mailer = configurationfactory.getmailer(); public void DoSomething() // do something with mailer _Mailer.Send(); // common public interface IMailer string Email get; set; string Smtp get; set; void Send(); // Providers public class Mailer : IMailer public string Email get; set; public string Smtp get; set; public void Send()

// MessageBox.Show(string.Format("0, 1", Email,Smtp)); Organiser la solution <?xml version="1.0" encoding="utf-8"?> <configuration> <configsections> <section name="onesection" type="configurationdemo.core.configuration.onesectionconfigurationsection,configuratio ndemo.core"/> </configsections> <onesection> <!--type pointe sur Mailer à créer--> <mailer name="defaultmailer" type="configurationdemo.providers.mailer,configurationdemo.providers" email="xx@xx.fr" smtp="xxx.gmail.com"/> </onesection> </configuration> 2. ConfigurationCollection <?xml version="1.0" encoding="utf-8"?> <configuration> <configsections> <section name="sectiontwo" type="configurationdemo.sectiontwoconfigurationsection,configurationdemo"/> </configsections> <sectiontwo> <Elements>

<add name="elementone" email="xx@xx.fr" /> <add name="elementtwo" email="xx@xx.com" /> </Elements> </sectiontwo> </configuration> public class SectionTwoConfigurationSection : ConfigurationSection [ConfigurationProperty("Elements", IsDefaultCollection = false)] [ConfigurationCollection(typeof(SectionTwoElementCollection))] public SectionTwoElementCollection Elements get return (SectionTwoElementCollection)base["Elements"]; [ConfigurationCollection(typeof(SectionTwoElement))] public sealed class SectionTwoElementCollection : ConfigurationElementCollection protected override ConfigurationElement CreateNewElement() return new SectionTwoElement(); protected override object GetElementKey(ConfigurationElement element) return ((SectionTwoElement)element).Name; public class SectionTwoElement : ConfigurationElement [ConfigurationProperty("name", IsRequired = true, IsKey = true)] public string Name get return (string)base["name"]; set base["name"] = value; [ConfigurationProperty("email", IsRequired = true)] public string Email get return (string)base["email"]; set base["email"] = value; var config = ConfigurationManager.GetSection("sectionTwo") as SectionTwoConfigurationSection; 3. Module + Pipeline Le module peut être chargé à partir du fichier de config.

On a d un côté les events De l autre des modules avec une méthode initialize dans laquelle celui-ci s abonne à un event. Events public delegate void ModuleDelegate<T>(T e); public class ProcessedEvents public ModuleDelegate<ModuleOneEventArgs> ModuleOneProcessed get; set; public ModuleDelegate<ModuleTwoEventArgs> ModuleTwoProcessed get; set; public class ModuleOneEventArgs : EventArgs public ModuleOneEventArgs() public class ModuleTwoEventArgs : CancelEventArgs public ModuleTwoEventArgs() Modules public interface IModule void Initialize(ProcessedEvents events);

public class ModuleOne : IModule public string Value = ""; public void Initialize(ProcessedEvents events) events.moduleoneprocessed += OnModuleOneProcessed; private void OnModuleOneProcessed(ModuleOneEventArgs e) // do something Value = "Ok"; public class ModuleTwo : IModule public void Initialize(ProcessedEvents events) events.moduletwoprocessed += OnModuleTwoProcessed; private void OnModuleTwoProcessed(ModuleTwoEventArgs e) if (MessageBox.Show("Cancel?", "Cancel", MessageBoxButton.OKCancel) == MessageBoxResult.OK) e.cancel = true; En cas d interaction avec une base de données on peut encadrer le code avec une transaction : string result = ""; bool cancel = false; // events partagés var events = new ProcessedEvents(); // modules abonnés à un event var moduleone = new ModuleOne(); moduleone.initialize(events); var moduletwo = new ModuleTwo(); moduletwo.initialize(events); using (var scope = new TransactionScope()) // event 1 if (events.moduleoneprocessed!= null) var args = new ModuleOneEventArgs(); events.moduleoneprocessed(args); result = moduleone.value; // event 2 if (events.moduletwoprocessed!= null)

var args = new ModuleTwoEventArgs(); events.moduletwoprocessed(args); if (args.cancel) //MessageBox.Show("Canceled"); // throw new ApplicationException(); cancel = true; if (!cancel) scope.complete(); 4. Override Consiste à créer des classes avec des méthodes virtuelles. La classe pourra être héritée facilement afin de redéfinir les méthodes. Il suffit en plus d ajouter une propriété accessible avec un test à l initialisation : public class DefaultCache protected readonly Dictionary<Type, Dictionary<string, object>> Cache = new Dictionary<Type, Dictionary<string, object>>(); public virtual void Register(Type type, string name, object instance) if (!Cache.ContainsKey(type)) Cache[type] = new Dictionary<string, object>(); if (!Cache[type].ContainsKey(name)) Cache[type][name] = instance; public class ReplacementCache : DefaultCache public override void Register(System.Type type, string name, object instance) // private DefaultCache _cache; public DefaultCache Cache get if (_cache == null) _cache = new DefaultCache(); return _cache;

set _cache = value; Ainsi on remplace facilement la classe de base Cache = new ReplacementCache(); 5. Mef / Composition On utilise la reflection pour récupérer les éléments exportés et les utiliser à la volée. public partial class MainWindow : Window public MainWindow() InitializeComponent(); AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); CompositionContainer container = new CompositionContainer(catalog); speaker = container.getexportedvalue<speaker>(); Speaker speaker; private void okbutton_click(object sender, RoutedEventArgs e) var message = speaker.dosayhello(tb.text); MessageBox.Show(message); [Export] public class Speaker [Import("SayHello")] public Func<string, string> DoSayHello; public class HelperMethods [Export("SayHello")] public string SayHello(string name) var message = string.format("hello 0!", name); return message; 0 ou 1 [Import(AllowDefault=true)] 1 Utiliser [Import] 0..* (enumerable) utiliser [ImportMany]

InheritedExport (héritage) [ExportMetadata] + Lazy IEnumerable<Lazy<Func<int,int>> lazymethods; ImportingConstructor (injection dans le constructor) Obtenir les exports GetExport <>(),GetExports (),GetExports<>() Obtenir une instance GetExportedValue<>(),GetExportedValueOrDefault<>(),GetExportedValues<>(), returns Lazy<T>()