Another .NET Blog

To content | To menu | To search

Wednesday 1 September 2010

[PostSharp] Fire INotifyPropertyChanged.OnPropertyChanged for read-only properties depending on other properties

One problem of the INotifyPropertyChanged aspect concerns automatic notification of read-only properties which depend on other properties.

Indeed, say you have this class, on which the aspect is applied:

[NotifyPropertyChanged]
public class Test
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string FullName { get { return FirstName + " " + LastName; } }
}

If you change the values of FirstName or LastName, the OnPropertyChanged event will be fired, and the view will be able to display the new values of the properties. But if a control of your view is bound to the FullName property, it won't be updated. A solution would be to declare FullName as an automatic property, and update it in the setters of FirstName and LastName. Not very practical.

In this article, I will show you how to extend the aspect, in order to make it fire the event for dependent properties when a "parent" property is modified.

Continue reading...

Monday 23 August 2010

[Ninject] Use one database session per view-model

One very useful web page I've read before beginning to code on my new project was this one: Data Access - Building a Desktop To-Do Application with NHibernate, from the well-known Ayende. In this article, among other hints and best-practices, he says, at the end of the Managing Sessions chapter:

The recommended practice for desktop applications is to use a session per form, so that each form in the application has its own session. Each form usually represents a distinct piece of work that the user would like to perform, so matching session lifetime to the form lifetime works quite well in practice. The added benefit is that you no longer have a problem with memory leaks, because when you close a form in the application, you also dispose of the session. This would make all the entities that were loaded by the session eligible for reclamation by the garbage collector (GC).

There are additional reasons for preferring a single session per form. You can take advantage of NHibernate’s change tracking, so it will flush all changes to the database when you commit the transaction. It also creates an isolation barrier between the different forms, so you can commit changes to a single entity without worrying about changes to other entities that are shown on other forms.

While this style of managing the session lifetime is described as a session per form, in practice you usually manage the session per presenter.

We'll see now how to implement this behavior, with Caliburn as the MVVM client framework, and Ninject as the dependency injector.

Continue reading...

Wednesday 4 August 2010

[PostSharp] How to virtualize all the methods of a class

When using NHibernate, it is recommended to declare the public and protected properties and methods of your entities as virtual, to be able to use them with proxies.

But missing a virtual keyword for a member of a POCO is easily forgettable, and unfortunately, you will only be warned of your mistake on runtime, when your mappings are being built.

In this article, I will show you how to 'not care' anymore about that, and let PostSharp do this stuff for us.

Continue reading...

Sunday 1 August 2010

End of holidays, and articles to come...

I'm back from 2 weeks of holidays, which partly explains why there wasn't a lot of articles recently.

Now that I'm full of energy, I will have more time to write some new stuff here on this blog. I have a few ideas of the topics I will address, but my next two articles should rely on:

  • PostSharp, and an aspect to virtualize all the methods of a class (to be used on POCO classes, so they can be used with NHibernate)
  • Ninject, and a solution to use one NHibernate session per View-Model in a WPF application, as recommended by Ayende Rahien here.

After these 2 articles, I don't know yet what I will write about. This is going to be the surprise...

See you soon!

Thursday 15 July 2010

[PostSharp] [FluentValidation] Automatic entity validation with IDataErrorInfo

This post is an english translation of this french post.

One way to manage data validation when using WPF is to implement the interface IDataErrorInfo on the classes to validate, and to modify the XAML file so that WPF automatically uses the functions of this interface to validate the value of the properties (See here for an example).

The problem with this, is that you have to alter your entities to add some logic inside them, which makes them become more than entities. One way to avoid that is provided by FluentValidation, which allows you to deport the validation logic outside of your entities, inside another class, where you can define some validation rules for your entity.

But as we always want our entities to continue to implement IDataErrorInfo, we have to operate a mix with FluentValidation. You can find a way to achieve that in this thread.

This thread was the starting point of the solution I'm going to propose to you, to fix this problematic in an easy way...

Continue reading...

[PostSharp] [Caliburn] - Automatically call NotifyOfPropertyChange on the view models

Here, I won't explain what are Caliburn and PostSharp. Their respective documentations, examples and samples already do that very well. But I will show you how to create an aspect which will be applied by PostSharp on the view models of a WPF assembly.

And as a result, on runtime, each time a public property will be changed, the event PropertyChanged of the interface INotifyPropertyChanged will be fired, and the WPF view will be able to refresh its state.

If you already know PostSharp, or have been on their website, you have certainly noticed that they already propose an aspect which intends to implement the interface INotifyPropertyChanged, and to call PropertyChanged when the value of a property is changed.

And if you already know Caliburn, you know that the classes you must inherit from to implement your view models inherit themselves from an abstract class named PropertyChangedBase, which implements INotifyPropertyChanged, and which proposes a function named NotifyOfPropertyChange, to which you give as a parameter the name of the modified property.

The aspect I'm going to show you will allow us to mix these 2 methods.

Continue reading...

Monday 28 June 2010

[PostSharp] [FluentValidation] Validation de classes grâce à IDataErrorInfo

Une manière de gérer la validation des données lorsqu'on utilise WPF est de faire implémenter l'interface IDataErrorInfo par les classes à valider, et de modifier votre fichier XAML pour que WPF utilise automatiquement les fonctions de cette interface pour valider la valeur des propriétés. (Un exemple en action ici).

Le souci avec cette méthode est que vos entités deviennent un peu plus que des entités de base. Et vous vous dites que finalement, ça ne serait pas mal d'externaliser la validation de ces entités dans une autre classe. Et pourquoi pas de définir des règles que votre entité se doit de respecter pour être valide. Pour cela, il existe FluentValidation.

Mais pour continuer à utiliser IDataErrorInfo, on doit maintenant utiliser FluentValidation au sein des fonctions définies par IDataErrorInfo. C'est ce que propose ce thread dans le forum de FluentValidation.

C'est en partant de cet article que je vais vous montrer le cheminement qui m'a amené à utiliser PostSharp pour régler en beauté (j'espère en tout cas) cette problématique.

Continue reading...

Tuesday 22 June 2010

[PostSharp] [Caliburn] - Appeler automatiquement NotifyOfPropertyChange pour les ViewModels

Dans cet article, je ne vais pas vous expliquer ce que sont Caliburn et PostSharp, leurs documentations et exemples respectifs le font déjà très bien, mais je vais expliquer comment créer un aspect que Postsharp va appliquer à des classes que nous définirons, et qui aura pour résultat d'implémenter l'interface INotifyPropertyChanged dans ces classes, et d'appeler automatiquement l'évènement PropertyChanged lorsque la valeur des propriétés publiques de ces classes va être modifiée.

Si vous connaissez déjà Postsharp, ou avez été regardé sur leur site, vous aurez sûrement remarqué qu'il existe déjà un aspect qui permet d'implémenter l'interface INotifyPropertyChanged, et d'appeler PropertyChanged à chaque changement de valeur de la propriété.

De même, si vous connaissez Caliburn, vous aurez également remarqué que les classes dont vous devez dériver pour implémenter vos ViewModels dérivent elles-même d'une classe abstraite nommée PropertyChangedBase, qui implémente INotifyPropertyChanged, et qui propose une fonction nommée NotifyOfPropertyChange, à laquelle vous passez comme paramètre le nom de la propriété qui a été modifiée.

L'aspect que je vais vous montrer va nous permettre de mixer ces 2 approches.

Continue reading...

Monday 17 May 2010

Rx: Nouvelle release

Une petite news rapide pour vous informer qu'une nouvelle version des Reactive Extensions a vu le jour vendredi dernier.

La release note se trouve ici. Et pour télécharger tout ça, c'est .

Et si vous ne connaissez pas cette API, n'hésitez pas à aller faire un tour ici, pour y découvrir les quelques articles que je lui ai consacré.

Thursday 13 May 2010

Rx: Exécuter une action de manière asynchrone

Pour clore le chapitre sur l'utilisation de Rx pour mon application de gestion de mises à jour, je vais terminer comme annoncé par vous montrer comment je lance les exécutables téléchargés de manière asynchrone, afin de ne pas bloquer le thread de la vue pendant l'installation.

Continue reading...

Wednesday 12 May 2010

Rx: Fusionner plusieurs Observable en un seul

Cet article est un prolongement de l'article précédent, puisqu'après avoir vu comment lancer le téléchargement de toutes les mises à jour et être notifié quand tout est terminé, nous allons cette fois voir comment récupérer une liste d'observables (chacun d'entre eux correspondant à l'installation d'une mise à jour), les fusionner en un seul, afin de pouvoir exécuter les mises à jour les unes après les autres, avec un arrête automatique dès lors qu'une mise à jour se passe mal.

Continue reading...

Tuesday 11 May 2010

Rx: Exécuter plusieurs observables et attendre qu'ils soient tous terminés

On continue avec la petite série d'articles Rx avec cette fois une nouvelle résolution de "problème". On a vu lors de l'article précédent comment ignorer les erreurs lorsque des adresses de téléchargement étaient invalides ou injoignables. Nous allons voir cette fois-ci comment lancer tous les téléchargements simultanément et comment attendre qu'ils soient tous terminés avant de les exécuter les uns après les autres pour les installer.

Continue reading...

Monday 10 May 2010

Rx: Opérateur Catch, ou comment ignorer des erreurs

Suite à mon article introductif sur les Reactive Extensions, je vais enchainer sur le même sujet une série d'articles (6 pour le moment sont prévus), bien plus courts que le dernier en date, et qui se focaliseront sur une manière de faire ou résoudre un problème précis que l'on peut rencontrer en utilisant cette API. Le premier article, ici-même, va s'attarder sur l'une des méthodes d'extension de Rx: Catch. Qui comme son nom le laisse supposer, a à voir avec les exceptions.

Continue reading...

Monday 12 April 2010

Introduction aux Reactive Extensions : Télécharger un fichier en asynchrone

J'ai déjà parlé à plusieurs reprises des reactives extensions, que l'on appelle plus familièrement Rx. Je me suis dit que ce serait une bonne idée que de vous les présenter plus en détail. Je ne vais pas écrire un article qui va tout vous expliquer depuis le début, car il existe déjà beaucoup de ressources. (ici, ici, ou bien ici, ou même encore ) Je me suis donc dit que ça serait peut-être une meilleure idée que de vous expliquer comment ça peut fonctionner grâce à un exemple concret. Et comme j'avais déjà un article expliquant comment réaliser une opération asynchrone en utilisant la TPL, j'ai repris cet exemple, en utilisant cette fois Rx.

Continue reading...

Tuesday 6 April 2010

Aide à l'injection de dépendances pour Ninject grâce à une interface "fluent"

Je vais aujourd'hui vous présenter le résultat d'un refactoring de masse dans une série de tests unitaires, qui a permis d'accroitre très fortement la lecture des tests, et surtout leur compréhension.

La classe testée a pour but de gérer les mises à jour d'une liste de programmes installés sur un ordinateur. Cette classe est très "high-level" dans la mesure où elle permet d'aller récupérer la liste de toutes les mises à jour de toute une gamme de produits, de savoir pour chaque programme quelles sont les mises à jour à installer, puis bien évidemment de télécharger ces mises à jour et les installer.

Comme vous le voyez, cette classe consiste en beaucoup de sous-tâches, qui vont toutes communiquer avec le monde extérieur (internet notamment, pour l'obtention des mises à jours et leur téléchargement). Dans le but d'obtenir des tests unitaires les plus isolés possibles, j'en suis bien sûr arrivé à décomposer chacune de ces sous-tâches et à les identifier par des interfaces bien distinctes, pour lesquelles je laisse à Ninject le soin de les injecter comme il faut.

Rien que du très classique en somme. Le hic étant que cette classe nécessite du coup l'injection de beaucoup de dépendances (5 !) et que la mise en place des mocks dans chaque test rend le test trop long, et sa relecture difficile.

Voici donc une solution pour éviter ce genre de soucis. Solution qui se base, comme vous allez le constater, sur une hiérarchie de Providers Ninject, et une classe de construction d'un Module, qu'on rendra "Fluent".

Continue reading...

Monday 8 March 2010

Reactive Extensions

En fin de semaine dernière est sortie la dernière release des Reactive Extensions.

Beaucoup de changements sur la release note, mais on notera principalement la compatibilité .Net 4 RC.

A voir également, une vidéo de 22' sur Channel 9.

Source : Bart De Smet'S

Saturday 20 February 2010

Resharper 5 beta 2

Un petit billet pour vous informer, si vous ne l'étiez pas déjà bien sûr, de la disponibilité toute récente de Resharper en beta 2 s'il vous plait!

A télécharger donc d'urgence si vous bossez sous VS2010!

Wednesday 10 February 2010

Copie d'objets

La copie d'objets en C# est vraiment un vaste débat, dans lequel il est facile de se perdre au vu des différentes solutions proposées lorsque vous faites une petite recherche sur Google.

Je vais essayer dans cet article d'expliquer pourquoi il ne vaut mieux pas utiliser l'interface ICloneable du framework, les 2 types de copie réalisables en C#, et je finirai par un exemple concret qui mettra en évidence (qui le tentera du moins) quelle méthodologie appliquer en fonction de ce que vos classes ont à copier.

Continue reading...

Monday 25 January 2010

Classe Helper pour gérer soi-même le DoubleBuffering d'un contrôle Winforms

Le souci

J'ai récemment du implémenter le dessin d'une grille (comme dans l'éditeur de Visual Studio par exemple) sur un contrôle de type Panel. Innocemment, mon premier essai a été de m'abonner à l'évènement OnPaint du contrôle, et d'ajouter le code suivant:

private void Foo_Paint(object sender, PaintEventArgs e)
{
    using (Pen pen = new Pen(Color.Gray, 1))
        for (int x = 10; x < e.ClipRectangle.Width; x += 10)
            for (int y = 10; y < e.ClipRectangle.Height; y += 10)
                e.Graphics.DrawRectangle(pen, new Rectangle(new Point(x, y), new Size(1, 1)));
}

Je lance l'application, j'ai bien une grille qui est dessinée. Souci: dès que la form est rafraichie (quand on la redimensionne, ou qu'on change les propriétés d'un de ses contrôles enfants), la grille est redessinée, ce qui entraine de violentes lenteurs de l'affichage, avec du bon gros flickering.

La solution pour éviter ce souci est d'utiliser la technique du double-buffering.

La solution

Nous allons implémenter cette stratégie du double-buffer en créant une nouvelle classe, qui prendra en paramètre le contrôle à utiliser, ce qui nous permettra de réutiliser facilement et à moindre frais le code. L'idée est d'utiliser les classes BufferedGraphicsContext et BufferedGraphics pour dessiner l'arrière-plan du contrôle dans un buffer, et quand le contrôle doit se redessiner, on applique le contenu du buffer directement dans le contrôle. Et c'est donc en évitant le dessin progressif de l'arrière-plan du contrôle que l'on va éviter le scintillement.

Mais voici tout de suite la première version de notre classe:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Tools.GUI
{
    public class DoubleBuffer : IDisposable
    {
        private readonly Control control;
        private bool dirty;
        private BufferedGraphicsContext bufferedGraphicsContext;
        private BufferedGraphics bufferedGraphics;

        public DoubleBuffer(Control control)
        {
            this.control = control;

            bufferedGraphicsContext = new BufferedGraphicsContext();

            CreateGraphicsBuffer();

            this.control.SizeChanged += control_SizeChanged;
        }

        void control_SizeChanged(object sender, EventArgs e)
        {
            CreateGraphicsBuffer();
        }

        private void CreateGraphicsBuffer()
        {
            if (bufferedGraphics != null)
            {
                bufferedGraphics.Dispose();
                bufferedGraphics = null;
            }

            if (bufferedGraphicsContext == null || control.DisplayRectangle.Width <= 0 || control.DisplayRectangle.Height <= 0)
                return;

            using (Graphics graphics = control.CreateGraphics())
                bufferedGraphics = bufferedGraphicsContext.Allocate(graphics, control.DisplayRectangle);

            Dirty = true;
        }

        private bool Dirty
        {
            get { return dirty; }
            set
            {
                if (!value)
                    return;

                dirty = true;
                control.Invalidate();
            }
        }

        public void Dispose()
        {
            if (bufferedGraphics != null)
            {
                bufferedGraphics.Dispose();
                bufferedGraphics = null;
            }

            if (bufferedGraphicsContext != null)
            {
                bufferedGraphicsContext.Dispose();
                bufferedGraphicsContext = null;
            }
        }
    }
}

On commence par créer une nouvelle instance de la classe BufferedGraphicsContext, puis on crée l'instance de BufferedGraphics grâce à l'appel de la fonction CreateGraphicsBuffer, où l'on commence par supprimer l'instance existante, puis où l'on crée effectivement la nouvelle instance grâce à un appel à la fonction Allocate de BufferedGraphicsContext, qui prend en paramètre le Graphics du contrôle, ainsi que le rectangle correspondant à la surface affichée du contrôle. Vous aurez remarqué que l'on ne crée pas le buffer si le contrôle a une largeur ou une hauteur égale à zéro.

Comme on a un nouveau buffer, on met le flag Dirty à true, qui aura pour conséquence de forcer un ré-affichage du contrôle via l'appel de Invalidate() (dans le setter de Dirty). Dans le constructeur de la classe, on s'abonne également à l'évènement SizeChanged du contrôle, car nous devons toujours avoir un buffer qui ait les mêmes dimensions que le contrôle.

C'est bien beau, mais nous n'affichons toujours rien pour le moment. Nous allons corriger ça de suite, on commençant par nous abonner à l'évènement OnPaint du contrôle, dans le constructeur de la classe:

public DoubleBuffer(Control control)
{
	this.control = control;

	bufferedGraphicsContext = new BufferedGraphicsContext();

	CreateGraphicsBuffer();

	this.control.SizeChanged += control_SizeChanged;
	this.control.Paint += control_Paint;
}

Nous allons ensuite définir la fonction control_Paint:

void control_Paint(object sender, PaintEventArgs e)
{
	if (bufferedGraphics == null)
	{
		Draw(e.Graphics);
		return;
	}

	if (Dirty)
	{
		Dirty = false;
		Draw(bufferedGraphics.Graphics);
	}

	bufferedGraphics.Render(e.Graphics);
}

Le fonctionnement du double buffer se fait ici: si on n'a pas de buffer (par exemple, le contrôle a sa largeur ou sa hauteur qui est nulle) , on va dessiner le contenu de l'arrière-plan du contrôle normalement, en passant à la fonction Draw le Graphics du contrôle, auquel on accède grâce à la propriété Graphics de PaintEventArgs. Si par contre on a un buffer, on commence par regarder l'état du flag Dirty. S'il est à true, c'est que l'on doit redessiner le buffer, ce qui est fait en passant la propriété Graphics de la classe BufferedGraphics. Et pour terminer, on appelle la fonction Render de BufferedGraphics, qui va écrire le contenu du buffer directement dans l'objet Graphics donné en paramètre, c'est à dire dans le Graphics du contrôle, provoquant donc l'affichage du contrôle.

Nous faisons mention dans le code précédent d'une fonction Draw, que voici:

private void Draw(Graphics graphics)
{
	if (control.ClientRectangle.Width <= 0 || control.ClientRectangle.Height <= 0)
		return;

	using (SolidBrush backBrush = new SolidBrush(control.BackColor))
		graphics.FillRectangle(backBrush, control.ClientRectangle);
}

Tout ce que fait cette fonction pour le moment, c'est juste de remplir l'arrière-plan du contrôle avec la couleur définie par la propriété BackColor. Pas très intéressant donc. Il serait bien de pouvoir définir des fonctions à exécuter dans la fonction Draw, afin de personnaliser l'affichage, et de profiter du double buffering mis en place. Nous allons arriver à ça en utilisant une liste d'actions, qui seront exécutées à la fin de la fonction Draw. Les actions étant enregistrées par l'utilisateur de la class DoubleBuffer via une fonction RegisterPaintAction.

Nous allons commencer par ajouter un nouveau membre à notre classe:

private readonly List<Action<Graphics, Rectangle>> paintDelegates = new List<Action<Graphics, Rectangle>>();

Puis nous exécutons la liste des actions dans la fonction Draw:

private void Draw(Graphics graphics)
{
    if (control.ClientRectangle.Width <= 0 || control.ClientRectangle.Height <= 0)
        return;

    using (SolidBrush backBrush = new SolidBrush(control.BackColor))
        graphics.FillRectangle(backBrush, control.DisplayRectangle);

    paintDelegates.ForEach(action => action(graphics, control.DisplayRectangle));
}

Et nous créons les fonctions d'enregistrement et de dés-enregistrement des actions (utile pour par exemple afficher ou pas la grille):

public void RegisterPaintAction(Action paintDelegate)
{
    if (paintDelegate == null)
        return;

    paintDelegates.Add(paintDelegate);

    Dirty = true;
}

public void UnregisterPaintDelegate(Action paintDelegate)
{
    if (paintDelegates.Remove(paintDelegate))
        Dirty = true;
}

On met le flag Dirty à true quand on ajoute une nouvelle action pour forcer un ré-affichage du contrôle immédiat.

Et voilà! Et pour utiliser tout ça, un petit exemple d'affichage de grille dans l'arrière-plan de la form:

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private readonly DoubleBuffer doubleBuffer;
        
        public Form1()
        {
            InitializeComponent();

            doubleBuffer = new DoubleBuffer(this);

            doubleBuffer.RegisterPaintAction((graphics, rectangle) =>
                                                   {
                                                       using (Pen pen = new Pen(Color.Gray, 1))
                                                           for (int x = 10; x < rectangle.Width; x += 10)
                                                               for (int y = 10; y < rectangle.Height; y += 10)
                                                                   graphics.DrawRectangle(pen, new Rectangle(new Point(x, y), new Size(1, 1)));
                                                   });
        }
    }
}

C'est tout pour cette fois ;) N'hésitez pas à me laisser vos impressions ou vos retours sur ce code!

PS: je joins à cet article le code complet de la classe DoubleBuffer.

Monday 14 December 2009

"Magic" null argument testing

Trouvée ici, une astuce vraiment *TRES* tricky, qui permet de simplifier (?) le test sur la "nullité" d'un ou plusieurs arguments, le tout à base d'expression trees et de types anonymes...

Continue reading...

- page 1 of 2