Dans ce post, j'essaye d'apporter une solution générique au problème de gestion des statuts possibles d'un objet.
Ex : Si une barre de menus possède plusieurs boutons (1 à N), on veut qu'à un instant t, on puisse commander facilement lesquels de ces N boutons sont visibles et lesquels sont invisibles.
Beaucoup de cas sont analogues à cette problématique.
1-Pour ces N objets , créons un Enum ( ayant N valeurs possibles ):
[Flags]
public enum Status
{
Status1 = 1,
Status2 = 2,
Status4 = 4,
Status8 = 8 }
Ici j'ai pris le cas de N = 4, la solution reste valable par récurrence.
Notez que les valeurs ne sont pas prises au hasard. (1,2,4,8....) est une suite géometrique de raison 2, le premier élément étant Math.Pow(2,0) = 1.
L'attribut [Flags] permet de faire des opérations "Binaire" sur ces valeurs ( AND, OR, NOT,...).
2-Sur les N objets, utiliser le pattern "Decorateur" pour décorer ces objets avec une propriété supplémentaire permettant de stocker le statut associé à l'objet.
Pour simplifier , je vais simplement ajouter directement cette propriété directement à l'objet.
public class Element
{
//propriete standart
public int Id { get; set; }
//propriétés supplémentaires
public Status Status { get; set; } //permet d'attribuer un statut à l'objet
public bool ToBeDisplay { get; set; } //état de l'objet à l'instant T
}
3- Sur les N objets, associez un status sur chaque objet ( relation One-To-One )
Element e1 = new Element() { Id = 1, Status = Status.Status1 };
Element e2 = new Element() { Id = 2, Status = Status.Status2 };
Element e4 = new Element() { Id = 4, Status = Status.Status4 };
Element e8 = new Element() { Id = 8, Status = Status.Status8 };
4- Je regroupe ensuite l'objet dans une liste
List<Element> elements = new List<Element>();
elements.Add(e1);
elements.Add(e2);
elements.Add(e4);
elements.Add(e8);
5- Voici la fonction Configure qui va permettre de positionner la valeur de la propriété ToBeDisplay en fonction d'un flag entré en paramètre :
private static List<Element> Configure(List<Element> elts,int flag)
{
Status f = (Status)(Enum.Parse(typeof(Status),flag.ToString()));
foreach (var item in elts)
{
bool isToBeDisplayed = false;
isToBeDisplayed = (item.Status & f ) == item.Status;
item.ToBeDisplay = isToBeDisplayed;
}
return elts;
}
-flag : variable de type int que l'on va caster en Status afin de pouvoir faire une opération binaire sur cette variable.
-Sur chaque élément, positionnez la propriété isToBeDisplayed .
- la ligne isToBeDisplayed = (item.Status & f ) == item.Status; permet de jongler sur le champ Status courant de l'objet et le flag.
Les valeurs de flag qui permettent de faire les combinaisons possibles sont sur l'intervalle: [1,Math.Pow(2,N)-1]
Dans notre cas N = 4, les valeurs de Flag intéressantes sont : 1,2,3,4,5,...15
Voici le programme complet :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
[Flags]
public enum Status
{
Status1 = 1,
Status2 = 2,
Status4 = 4,
Status8 = 8,
}
public class Element
{
public Status Status { get; set; }
public int Id { get; set; }
public bool ToBeDisplay { get; set; }
}
class Program
{
static void Main(string[] args)
{
Element e1 = new Element() { Id = 1, Status = Status.Status1 };
Element e2 = new Element() { Id = 2, Status = Status.Status2 };
Element e4 = new Element() { Id = 4, Status = Status.Status4 };
Element e8 = new Element() { Id = 8, Status = Status.Status8 };
List<Element> elements = new List<Element>();
elements.Add(e1);
elements.Add(e2);
elements.Add(e4);
elements.Add(e8);
var r = Configure(elements, 7);
foreach (var item in r)
{
if (item.ToBeDisplay)
{
Console.WriteLine(item.Id);
}
}
Console.ReadLine();
}
private static List<Element> Configure(List<Element> elts,int flag)
{
Status f = (Status)(Enum.Parse(typeof(Status),flag.ToString()));
Console.WriteLine("status = " + f);
foreach (var item in elts)
{
bool isToBeDisplayed = false;
isToBeDisplayed = (item.Status & f ) == item.Status;
item.ToBeDisplay = isToBeDisplayed;
}
return elts;
}
}
}