Dot.Blog

Consulting DotNet C#, XAML, WinUI, WPF, MAUI, IA

Mettre des données en forme en une requête LINQ

Losqu'on traite de LINQ, la majorité des exemples utilisent des sources de données "bien formées" : flux RSS (mon dernier billet), collections d'objets, etc. Mais dans la "vraie vie" les sources de données à traiter sont parfois moins "lisses", moins bien formées. LINQ peut aussi apporter son aide dans de tels cas pour transformer des données brutes en collection d'objets ayant un sens. C'est ce que nous allons voir dans ce billet. Prenons un exemple simple : imaginons que nous récupérons une liste de rendez-vous depuis une autre application, cette liste est constituée de champs qui se suivent, les initiales de la personne, son nom et l'heure du rendez-vous. Tous les rendez-vous se suivent en une longue liste de ces trois champs mais sans aucune notion de groupe ou d'objet. Pour simplifier l'exemple, fixons une telle liste de rendez-vous dans un tableau de chaînes : string[] data = new[] { "OD", "Dahan", "18:00", "MF", "Furuta", "12:00", "BG", "Gates", "10:00" }; La question est alors comment extraire de cette liste "linéaire" les trois objets représentant les rendez-vous ? La réponse passe par trois astuces : L'utilisation de la méthode Select de LINQ qui sait retourner l'index de l'entité traitée La syntaxe très souple de LINQ permettant d'utiliser des expressions LINQ dans les valeurs retournées Et bien entendu la possibilité de créer des types anonymes Ce qui donne la requête suivante : var personnes = data.Select ( (s, i) => new                                           {                                              Value = s,                                              Bloc = i / 3                                           }                                         ).GroupBy(x => x.Bloc)                                         .Select ( g => new                                                      {                                                       Initiales = g.First().Value,                                                       Nom = g.Skip(1).First().Value,                                                       RendezVous = g.Skip(2).First().Value                                                      } ); L'énumération suivante :  foreach (var p in personnes.OrderBy(p=>p.Nom)) Console.WriteLine(p); donnera alors cette sortie console de toutes les personnes ayant un rendez-vous, classées par ordre alphabétique de leur nom : { Initiales = OD, Nom = Dahan, RendezVous = 18:00 } { Initiales = MF, Nom = Furuta, RendezVous = 12:00 } { Initiales = BG, Nom = Gates, RendezVous = 10:00 } Voici des objets bien formés (on pourrait ajouter un DateTime.Parse à la création du champ RendezVous pour récupérer une heure plutôt qu'une chaîne) qui pourront être utilisés pour des traitements, des affichages, une exportation, etc... LINQ to Object ajoute une telle puissance à C# que savoir s'en servir au quotidien pour résoudre tous les petits problèmes de développement qui se posent permet réellement d'augmenter la productivité, ce que tous les langages et IDE promettent falacieusement (aucune mesure de ce supposé gain n'existe). Ici, essayez d'écrire le même code sans LINQ, vous verrez tout suite que le gain de productivité et de fiabilité est bien réel, et que la maintenance aura forcément un coup moindre. Pour d'autres infos, Stay Tuned ! Le projet VS 2008 : LinqChunk.zip (5,35 kb)

Traiter un flux RSS en 2 lignes ou "les trésors cachés de .NET 3.5"

.NET 3.5 apporte beaucoup de classes nouvelles et d'améliorations à l'existant. Certains ajouts sont plus médiatisés que d'autres. Mais il serait injuste de limiter cette mouture à LINQ ou aux arbres d'expressions, aussi géniales et puissantes soient ces avancées. .NET 3.5 apporte réellement une foule de nouveautés parmi lesquelles il faut noter : L'apport de WCF et de LINQ au compact framework De nouvelles facilités pour contrôler le Garbarge Collector comme le LatencyMode de la classe GCSettings L'ajout de l'assemblage System.NetPeerToPeer.Collaboration qui permet d'utiliser les infrastructures de peer-to-peer Des améliorations importantes de WCF, l'intégration WCF-WF etc... Pour une liste complète des nouveautés il est intéressant de jeter un oeil à cette page MSDN. Un exemple qui illustre les avancées plus ou moins méconnues de .NET 3.5, l'espace de noms System.ServiceModel.Syndication dans la dll System.ServiceModel.Web apporte de nouvelles facilités pour gérer des flux RSS. Et pour s'en convaincre quelques lignes de codes : SyndicationFeed feed; using (var r = XmlReader.Create(https://www.e-naxos.com/Blog/syndication.axd)) { feed = SyndicationFeed.Load(r); } C'est tout ! Dans la variable "feed" on a tout ce qu'il faut pour travailler sur le flux RSS. Vous pensez que je triche et que "travailler sur le flux RSS" c'est certainement pas si simple que ça ?. Bon, allez, c'est parce que c'est vous : compliquons même la chose et, à partir de ce flux, affichons le titre de tous les billets qui parlent de LINQ dans leur corps. Voici le code complet près à compiler : using System; using System.Linq; using System.ServiceModel.Syndication; using System.Xml; namespace NET35RSS { class Program   {      static void Main()      {         SyndicationFeed feed;         using (var r = XmlReader.Create(https://www.e-naxos.com/Blog/syndication.axd))         { feed = SyndicationFeed.Load(r); }            if (feed==null) { Console.WriteLine("Flux vide."); return; }            Console.WriteLine(feed.Title.Text);            Console.WriteLine(feed.Description.Text+"\n");            var q = from item in feed.Items            where item.Summary.Text.ToUpper().Contains("LINQ") select item;            foreach (var item in q) Console.WriteLine(item.Title.Text);        }     } } Ajoutez une petite saisie pour le mot à chercher au lieu d'un codage en dur ("LINQ" dans cet exemple) et un petit fichier paramètre pour y stocker la liste des blogs que vous connaissez, et en deux minutes vous aurez un puissant outil de recherche capable de vous lister toutes les billets de vos blogs préférés qui parlent de tel ou tel sujet... C'est pas génial ça ? Si, ça l'est, bien sûr ! Alors Stay Tuned ! pour les paresseux du clavier, le projet VS 2008 : NET35RSS.zip (5,36 kb)

Un excellent livre sur LINQ : "LINQ in Action"

LINQ (encore ! dirons certains, mais c'est justifié je vous l'assure) est une technologie qui décuple la puissance de C#, encore faut-il bien maîtriser toutes les nouveautés syntaxiques de C# 3.0 (voir mes articles sur ce sujet*) et bien comprendre comment tirer partie du meilleur de LINQ lui-même. Pour cela rien ne vaut un bon livre. Sur le sujet ils ne sont pas très nombreux et quand on fait un peu le tri, il en reste fort peu qui valent l'achat. Ce n'est pas le cas de "LINQ in action" un excellent bouquin qui utilise une approche très pédagogique pour "monter en puissance" au fur et à mesure de la progression des chapitres. C'est d'ailleurs peut-être aussi parce que les auteurs reprennent justement cette logique que j'applique dans mes propres cours sur LINQ que j'apprécie ce livre. Il s'agit bien entendu d'un ouvrage en anglais, si vous ne maîtriser pas la langue il faudra hélas passer votre chemin. Les concepts avancés dans le livre peuvent s'avérer suffisament sophistiqués en eux-mêmes sans ajouter la difficulté de décryptage si on n'est pas totalement à l'aise avec la prose d'outre-Atlantique. Pour acheter le livre au moins cher, je vous conseille l'excellent librairie anglaise The Book Repository qui livre en France et qui applique des tarifs généralement hors concurrence. La page du livre est ici "Linq in Action". L'ouvrage possède aussi son propre site avec le téléchargement des exemples ainsi qu'un forum. (* Les nouveautés syntaxiques de C# 3.0 et Présentation des différentes facettes de LINQ )

LINQ et Réflexion pour obtenir les valeurs de System.Drawing.Color

LINQ... l'un de mes sujets préférés... Plus je l'utilise, à toutes les sauces, et plus je trouve cette technologie indispensable. Mais foin de propagande, voici encore un exemple qui prouve à quel point LINQ peut servir à tout, facilement. Le but du jeu : récupérer la définition des couleurs de System.Drawing.Color, en faire un tableau trié par ordre alphabétique. A la "main" je vous souhaite bien du plaisir... Avec LINQ cela donne la chose suivante : namespace LinqColor {   class Program   {      static void Main(string[] args)     {        var color_type = typeof(System.Drawing.Color);        var color_properties = from prop in color_type.GetProperties()                                      where prop.PropertyType == color_type                                      orderby prop.Name                                      select prop;               foreach (var color_property in color_properties)        {            var cur_color = (System.Drawing.Color) color_property.GetValue(null, null);            uint rgb_int = (uint) cur_color.ToArgb() & (0x00ffffff);            Console.WriteLine(" {0,-20} = ({1,-3},{2,-3},{3,-3}) = 0x{4:X00000000}",            color_property.Name,            cur_color.R, cur_color.G, cur_color.B,rgb_int);        }     }   } } La sortie écran (console) donne la chose suivante : Le projet VS 2008 pour les fénéants du clavier : LinqColor.zip (5,43 kb) C'est pas merveilleux LINQ ? Bien sûr que si... Alors Stay Tuned !

La bombe Parallèle ! PLINQ, et PCP Parallel Computing Platform

Le framework .NET n'en finit pas d'innover ! La bombe du jour c'est PLINQ et PCP. Vous ne connaissez pas encore ? Normal, ce n'est même pas encore sorti, juste en preview... Pour résumer en un mot : Révolutionnaire. Comme LINQ. L'objectif Vous l'avez certainement remarqué comme tout geek qui se respecte, depuis quelques années nos amis fondeurs ne se battent plus à coup de Ghz pour promouvoir leurs microprocesseurs... Les gammes se multiplient et surtout les coeurs ! Et le temps où le concepteur d'un soft trop lent pouvait toujours dire "je suis en avance c'est tout, avec la dernière génération de processeur mon soft est super rapide!", ce temps là est fini, révolu. Aujourd'hui un soft lent sur un dual core sera peut être même encore plus lent sur un quad core d'une autre série (il y a plein de séries de processeurs on ne s'y retrouve d'ailleurs plus pour choisir...). Donc, pour qu'un soft soit plus rapide, inutile de compter sur la prochaine génération de processeur qui doublera la fréquence d'horloge. Aujourd'hui on double le nombre de coeurs, c'est tout. un, puis deux, les quatre coeurs se banalisent, Intel avait annoncé (le tiendront ils) que d'ici peu de temps on atteindrait les 100 coeurs... Mais pour tirer partie de tous ces coeurs finalement pas si rapide, une seule solution le parallélisme ! Parallèlisme et programmation Seulement voilà, pour bénéficier de tous ces coeurs il faut programmer selon un mode parallèle. Le plus "simple" consiste à faire du multi-threading en laissant l'OS répartir les threads entre les coeurs, mais pour plein de raison (je vous laisse y réfléchir) cela n'est pas forcément optimal. Un simple exemple : une tâche un peu lourde, vous n'avez pas besoin de 50 threads, vous avez une grosse bonne boucle qui traite une image pour faire du morphing par exemple. Allez programmez ça en créant plusieurs threads ! Si vous y arriver sans y engloutir des semaines de mise au point, je veux bien manger mon chapeau (il faudra fournir le chapeau je n'en porte pas, et si vous le fournissez, ça ne sera pas le mien, donc je ne le mangerais pas. On ne m'a pas si facilement...) ! Car en effet, multiplier les threads n'est pas toujours réalisable, en tout cas simplement. Découper une tâche en sous tâches parallélisables est en réalité tellement complexe, surtout de façon générique, que les langages et les OS sont bien à la traîne par rapport aux microprocesseurs. A la traîne ? Pas tous... Car sous .NET il va falloir compter avec PLINQ et PCP ! PLINQ et PCP En très gros il s'agit d'extensions du framework .NET qui permet de paralléliser à peu près tout traitement sans presque aucune programmation particulière. Oui vous avez bien lu... Ainsi, PLINQ est une extension parallèle de LINQ. Une requête LINQ comme : var result = from c in liste where c.champ==5 orderby c.autreChamp select c; // version simple devient en parallèle : var result = from c in liste.AsParallel() where c.champ==5 orderby c.autreChamp select c; // parallélisée Et c'est tout ! D'un seul coup la requête devient parallèle et s'executera sur tous les coeurs disponibles à la fois, le boulot étant découpé, les threads créés, et tout le reste, de façon automatique par PLINQ. Un rêve ? Non, pas besoin de se pincer, c'est déjà en preview à télécharger ! (voir en fin de billet). Bien entendu il existe beaucoup de variantes et une syntaxe appropriée pour, par exemple, modifier le nombre de coeurs utilisés et plein d'autres nuances subtiles. La parallélisation de LINQ est une pure merveille, mais il y a aussi PCP qui est le framework plus généraliste permettant de paralléliser des foreach, des for, etc, juste avec un mot clé. Il existe là aussi toute une panoplie de méthodes qu'il va falloir découvrir. Mais vous avouerez que le bond en avant est aussi fantastique que celui de LINQ par exemple. Je ne pense sincèrement pas que quiconque ayant utilisé LINQ ne voudra dans l'avenir d'un langage ne supportant pas une telle extension. Il y a eu un avant LINQ, il y aura forcément un après LINQ, mais on ne traversa pas le temps sans faire référence à cette nouvelle ère, au sens premier, le clou d'airain planté par le prêtre dans la mur du temple de la Rome antique pour marquer un événement crucial d'une telle importance qu'une nouvelle série d'années commençait. PLINQ et PCP marqueront de la même façon une nouvelle ère. Faire joujou ? Je reconnais bien le geek qui sommeille en vous ! Oui c'est possible ! Il existe une CTP sortie en juin et qui est téléchargeable sur le site MSDN consacré à la programmation parallèle. Vous y trouverez de nombreuses informations qui complèteront facilement la très rapide présentation faite ici. Le site : http://msdn.microsoft.com/fr-fr/concurrency/ ... Vous êtes encore là ? Mais foncez je vous dit, c'est l'éclate du geek ce truc ! (mais pensez à revenir hein.. Stay Tuned !) [EDIT: lire aussi ce billet plus récent qui donne l'adresse d'un article sur PFX et de plusieurs Webcasts]