La version 0.3 de la librairie Dvp.NET est disponible !



En plus des nouvelles fonctionnalités, améliorations et corrections de bugs, la grosse nouveauté de cette version est le déploiement avec NuGet, qui va permettre de faciliter l'utilisation de Dvp.NET dans vos projets (si vous utilisez Visual Studio 2010).

NuGet est un gestionnaire de packages : vous sélectionnez la librairie que vous souhaitez utiliser dans une liste, et NuGet se charge de tout
  • il télécharge la version appropriée pour votre projet, selon la version du Framework que vous utilisez (2.0, 3.5, 4.0, Silverlight, Compact Framework...)
  • si le package nécessite d'autres packages, NuGet télécharge automatiquement les dépendances
  • si nécessaire, il ajoute automatiquement les sections de configuration adéquates dans le fichier app.config ou web.config
  • si des mises à jour existent pour les packages déjà installés, NuGet vous permet de les récupérer automatiquement

Vous trouverez ici toutes les instructions nécessaires pour installer les packages Dvp.NET à l'aide de NuGet.

Voici une liste à peu près exhaustive des changements apportés par cette version. Il y a quelques "breaking changes" ; désolé pour ceux que ça va toucher, mais c'est pour la bonne cause... a priori ce ne sera pas trop compliqué à corriger

  • Assembly Developpez.Dotnet
    • Classe EnumerableExtensions
      • Méthode ToHierarchy<T> : permet de convertir une collection "plate" d'objets en une collection de noeuds hiérarchique. On spécifie, via des delegates, le critère pour identifier les éléments racines et la relation entre parent et enfant, et on récupère une liste de noeuds racines qui représentent la hiérarchie. Un exemple sera plus parlant :
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        class Category
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int ParentId { get; set; }
        }
         
        ...
         
        var categories = GetCategories();
        var hierarchy = categories.ToHierarchy(
                        cat => cat.ParentId == 0, // catégories racines
                        (parent, child) => parent.Id == child.ParentId // relation parent-enfant
                    );
        Chaque élément de hierarchy est un objet Node<Category>, avec les propriétés suivantes :
        - Item : l'objet Category représenté par le noeud
        - Level : le niveau du noeud dans la hiérarchie
        - Parent : le noeud parent
        - Children : la liste des noeuds enfants

        De cette façon on peut facilement parcourir la hiérarchie, par exemple pour l'afficher sous forme d'arbre
      • Méthode Flatten<T> : en gros, c'est le contraire de la méthode ToHierarchy : ça renvoie une liste "plate" de tous les noeuds d'une hiérarchie. C'est un peu comme un SelectMany, sauf que ça le fait récursivement sur tous les niveaux (conceptuellement, c'est récursif, mais l'implémentation n'est pas récursive).
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        class Category
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public IList<Category> SubCategories { get; set; }
        }
         
        ...
         
        var rootCategories = GetRootCategories();
        var allCategories = rootCategories.Flatten(cat => cat.SubCategories);
      • Méthode IndexOfSequence<T> : recherche une sous-séquence dans une séquence (comme String.IndexOf, mais pour n'importe quel type). C'est vaguement inspiré de l'algorithme Knuth–Morris–Pratt, mais un peu adapté pour l'utilisation dans Linq (la séquence n'est énumérée qu'une fois, sans jamais revenir en arrière).
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        var numbers = new[] { 4, 8, 15, 16, 23, 42 };
        int i = numbers.IndexOf(new[] { 15, 16 }); // renvoie 2
      • Méthode Split<T> : permet de séparer une liste en plusieurs parties selon un critère arbitraire. On fournit un prédicat indiquant si un item donné est un séparateur.
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        var verses = File.ReadAllLines("poem.txt");
        var strophes = verses.Split(String.IsNullOrEmpty);
      • Méthode Apply<T> : correction d'un bug : ça ne marchait pas avec les types valeurs... Un nouvelle surcharge est disponible pour les types valeurs, qui prend un delegate avec un paramètre ref :
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        // Ne fonctionne pas car l'action est effectuée sur une copie
        MyStruct[] items = GetItems().Apply(s => s.X = 42).ToArray();
         
        // OK, l'objet est passé par référence
        MyStruct[] items = GetItems().Apply((ref MyStruct s) => s.X = 42).ToArray();
    • Classe StringExtensions
      • Méthode ToTitleCase : met une chaine en "title case", c'est à dire avec la première lettre de chaque mot en majuscule
      • Méthode Capitalize : met en majuscule le premier caractère d’une chaine
      • Méthode MatchesWildcard : vérifie si une chaine correspond à un pattern "wildcard", du type "*.exe", "foo?bar*baz"...
      • Ellipsis : permet de tronquer une chaine si elle est trop longue, en remplaçant si besoin les derniers caractères par des points de suspension (ou autre) :

        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        string s = "Ce texte est beaucoup trop long !";
        string s2 = s.Ellipsis(15); // "Ce texte est..."
      • Méthodes EnsureStartsWith/EnsureEndsWith : ajoute un préfixe ou un suffixe s'il n'est pas déjà présent
      • Méthode IsValidEmail : vérifie si une chaine est une adresse email valide
    • Classe NumberConverter (conversion d'un nombre en toutes lettres) :
      • Surcharge de Spell pour les nombres décimaux (double et decimal)
      • MéthodeSpellAmount : convertit en toutes lettres une somme en devise (pour la rédaction de chèques) :
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        decimal amount = 42.5;
        string textAmount = NumberConverter.SpellAmount(amount, "euro", "centime");
        // quarante-deux euros et cinquante centimes
    • Classe IBAN
      • Méthode FromRIB pour obtenir l'IBAN à partir d'un RIB
    • Classe RIB
      • Méthode FromIBAN pour obtenir le RIB à partir d'un IBAN
    • Classe ReflectionExtensions
      • Méthode ReflectionExtensions.IsStatic : indique si un type est statique
    • Classe LinqHelper
      • Méthodes GetProperty et GetMethod (équivalentes à GetPropertyName et GetMethodName, mais renvoient le PropertyInfo ou MethodInfo plutôt que le nom)
    • Classe DisposableAction : permet de s'assurer qu'une action est bien exécutée à la fin d'un bloc using
      Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      using(new DisposableAction(() => Console.WriteLine("Fini !")))
      {
          FaireQuelqueChose();
          ...
      }
    • Quelques améliorations de la classe StringTemplate : prise en compte des champs en plus des propriétés, gestion de certains corner-cases, ajout d'un paramètre optionnel throwOnMissingValue (indique qu'une exception doit être levée si la valeur correspondant au placeholder n'est pas trouvée)
    • Classe IniFile : corrections de bugs
      • Les noms de section comportant un point n'étaient pas reconnus
      • Les commentaires étaient mal gérés, un commentaire à la suite d'une valeur était considéré comme faisant partie de la valeur


  • Assembly Developpez.Dotnet.System
    • Classe FileUtils
      • Méthode GetFileTypeDescription : renvoie la description d'un type de fichier d'après le nom de fichier ou l'extension, tel qu'affiché dans l'explorateur Windows
      • Méthode GetDisplayName : récupère le nom d'affichage d'un fichier ou dossier, tel qu'affiché dans l'explorateur Windows. On peut passer un chemin ou un répertoire spécial (Environment.SpecialFolder) :
        Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        string displayName = FileUtils.GetDisplayName(@"C:\monfichier.zob");
        string myComputerName = FileUtils.GetDisplayName(Environment.SpecialFolder.MyComputer);
      • Méthode MakeRelativePath : crée un chemin relatif à partir de 2 chemins absolus
      • PathCombine a été renommé en CombinePaths, plus conforme aux guidelines pour les noms...
      • Corrigé bug potentiel en 64 bits sur des appels P/Invoke
    • Classes FileCopyOperation et FileMoveOperation : wrappers des API CopyFileEx et MoveFileWithProgress pour effectuer des copies et déplacements de fichier avec indication de la progression, via un évènement ProgressChanged :
      Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
          var op = new FileCopyOperation(sourcePath, destinationPath);
          op.ProgressChanged += (sender, e) =>
          {
              Console.WriteLine("Copying '{0}' to '{1}' ({2}% done)", e.Source, e.Destination, e.PercentDone);
          };
          op.Execute();

  • Assembly Developpez.Dotnet.Windows (WPF)
    • Restructuration du code : l'organisation des classes laissait un peu à désirer... Les namespaces ont été un peu réarrangés, les propriétés attachées ont été regroupées selon les contrôles auquels elles s'appliquent
    • Propriété attachée WindowBehavior.FadeOnClose : permet de faire un effet de fondu lors de la fermeture d'une fenêtre
    • Propriété attachée TextBoxBehavior.InfoText : pour ajouter un texte en filigrane (watermark) sur n'importe quelle TextBox ou PasswordBox. On peut aussi spécifier la couleur du texte en filigrane.
      Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      <TextBox dvp:TextBoxBehavior.InfoText="Login" />
      <PasswordBox dvp:TextBoxBehavior.InfoText="Password"
                          dvp:TextBoxBehavior.InfoTextForeground="Blue" />
    • Classe Mediator pour MVVM : permet de passer des messages entre les ViewModel de façon découplée :

      FooViewModel :

      Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      Mediator.Instance.Subscribe<HelloMessage>(
          (sender, m) =>
          {
              Console.WriteLine("Hello message received from {0} : {1}", sender, m.Text);
          });

      BarViewModel :

      Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
      Mediator.Instance.Post(this, new HelloMessage("Hello world !"));

      La classe utilise le pattern WeakEvent, de façon à éviter les fuites mémoires si un objet ne s'est pas désabonné.
    • Amélioration de ComboBoxBehavior : correction de bugs sur le filtre auto, ajout de propriétés FilterComparisonType et FilterMemberPath pour un contrôle plus fin du filtrage
  • La documentation est désormais disponible au format MS Help Viewer 1.0 (format VS2010)


N'hésitez pas à nous faire part de vos remarques, et à signaler les bugs sur le gestionnaire de projet