Accueil > > > PROPRIÉTÉS D'EXTENSION AVEC C# 3.0
PROPRIÉTÉS D'EXTENSION AVEC C# 3.0
Information sur la source
Description
Ceci est un code qui permet de simuler des propriétés d'extension grâce à aux méthodes d'extension de C# 3.0. L'idée est de définir 2 méthodes d'extension, l'une servant d'accesseur set et l'autre d'accesseur get, les valeurs étant prises et stockées dans un Dictionary. J'ai prévu pour cela deux façons de faire : - première méthode : la méthode servant d'accesseur set doit avoir un nom commençant par "Set", tandis que celle servant d'accesseur get doit avoir un nom commençant par "Get". Le reste des noms doit être égaux pour les 2 méthodes. Par exemple : public static string GetProperty(this IA i) public static void SetProperty(this IA i, string value) - deuxième méthode : les 2 méthodes portent le même nom mais des attributs "Get" et "Set" leurs sont associées. Par exemple : [Get] public static string AProperty(this IA i) { return string.Empty; } [Set] public static void AProperty(this IA i, string value) { } J'intercepte, les appels de ces méthodes afin de centraliser le remplissage/renvoi de valeurs vers/depuis mon Dictionary. J'utilise pour cela PostSharp (http://www.postsharp.org/). Je profite de cet outil pour vérifier à la compilation que les conditions citées plus haut sont bien remplies, que des attributs ne sont pas oubliés, que le type d'entré (type du paramètre de la méthode set) et de sorti (type de retour de la méthode get) correspondent,... En combinant ça avec des interfaces, on pourrait presque faire de l'héritage multiple...
Source
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using PostSharp.Laos;
- using System.Reflection;
- using PostSharp.Extensibility;
- using System.Text.RegularExpressions;
-
- namespace ExtensionProperties
- {
- /// <summary>
- /// Classe de base pour intercepter les méthodes d'extension "propriétés"
- /// </summary>
- [Serializable]
- public abstract class BasePropertyInterceptor : OnMethodBoundaryAspect
- {
- protected static PropertyContainer PropertyValues = PropertyContainer.GetInstance();
-
- public override void OnEntry(MethodExecutionEventArgs e)
- {
- OwnerType = e.Method.GetParameters()[0].ParameterType;
- Owner = e.GetArguments()[0];
- if (e.GetArguments().Length > 1)
- Value = e.GetArguments()[1];
- }
-
- public override void CompileTimeInitialize(MethodBase method)
- {
- MethodName = method.Name;
- }
-
- /// <summary>
- /// Type de l'objet portant la méthode-"propriété".
- /// </summary>
- public Type OwnerType { get; set; }
-
- /// <summary>
- /// Instance de l'objet portant la méthode-"propriété".
- /// </summary>
- public object Owner { get; set; }
-
- /// <summary>
- /// Nom de la méthode-"propriété".
- /// </summary>
- public virtual string MethodName { get; set; }
-
- /// <summary>
- /// Valeur de la propriété.
- /// </summary>
- public object Value { get; set; }
-
- [Serializable]
- protected class PropertyContainer : Dictionary<Type, Dictionary<object, Dictionary<string, object>>>
- {
- // Design pattern singleton
- private static PropertyContainer instance = null;
-
- private PropertyContainer() { }
-
- public static PropertyContainer GetInstance()
- {
- if (instance == null)
- instance = new PropertyContainer();
- return instance;
- }
-
- // Redéfinition d'indexeurs
- public object this[Type objtype, object obj, string propertyName]
- {
- get
- {
- try { return base[objtype][obj][propertyName]; }
- catch { return null; }
- }
- }
-
- public Dictionary<string, object> this[Type objtype, object obj]
- {
- get
- {
- try { return base[objtype][obj]; }
- catch { return null; }
- }
- }
- }
- }
-
-
- /// <summary>
- /// Attribut à associer à la classe contenant les méthodes d'extension. Il intercepte les méthodes d'extension "Get*"/"Set*" et renvoit/stock les valeurs.
- /// </summary>
- [Serializable]
- public class InterceptProperties : BasePropertyInterceptor
- {
- private Get _Getter;
- private Set _Setter;
-
- public override void CompileTimeInitialize(MethodBase method)
- {
- base.CompileTimeInitialize(method);
- if (method.Name.StartsWith("Get"))
- {
- CheckAccessorAttributes(method);
-
- // la méthode "Get" doit être sans paramètre.
- if (method.GetParameters().Length != 1)
- throw new Exception(string.Format("Une méthode dont le nom commence par \"Get\" a été trouvée, mais elle possède un ou plusieurs paramètres sans modificateur \"this\".", method.Name));
- var instance = method.GetParameters()[0];
-
- // on cherche une methode portée par la même classe, de même nom et possédant un attribut "Set".
- var presumedSetters = method.DeclaringType.GetMethods().Where(m => m.Name.StartsWith("Set") && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString());
- if (presumedSetters.Count() == 0)
- throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} dont le nom commence par \"Set\".", method.Name, instance.ParameterType));
- }
- if (method.Name.StartsWith("Set"))
- {
- CheckAccessorAttributes(method);
-
- // on vérifie que la méthode ne possède qu'un seul paramètre.
- ParameterInfo param;
- if (method.GetParameters().Length != 2)
- throw new Exception(string.Format("La méthode \"{0}\" définie comme accesseur \"set\" doit posséder un unique paramètre sans modificateur \"this\".", method.Name));
- param = method.GetParameters()[1];
- var instance = method.GetParameters()[0];
-
- // on cherche une methode portée par la même classe, de même nom et possédant un attribut "Get".
- var presumedGetters = method.DeclaringType.GetMethods().Where(m => m.Name.StartsWith("Get") && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString());
- if (presumedGetters.Count() == 0)
- throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} dont le nom commence par \"Get\".", method.Name, instance.ParameterType));
-
- // la méthode "Get" doit avoir une valeur de retour du même type que le paramètre de la méthode "Set".
- presumedGetters = presumedGetters.Where(m => m.ReturnType == param.ParameterType);
- if (presumedGetters.Count() == 0)
- throw new Exception(string.Format("Une méthode dont le nom commence par \"Get\" a été trouvée, mais le type de son paramètre de retour ne correspond pas à celui du paramètre de la méthode \"Set\".", method.Name));
- }
- }
-
- protected void CheckAccessorAttributes(MethodBase method)
- {
- var setAttr = method.GetCustomAttributes(typeof(Set), false);
- var getAttr = method.GetCustomAttributes(typeof(Get), false);
- if (setAttr != null && setAttr.Length != 0)
- throw new Exception(string.Format("La méthode \"{0}\" ne doit pas avoir d'attribut \"Set\" associé",method.Name));
- if (getAttr != null && getAttr.Length != 0)
- throw new Exception(string.Format("La méthode \"{0}\" ne doit pas avoir d'attribut \"Get\" associé",method.Name));
- }
-
- public override void OnEntry(MethodExecutionEventArgs e)
- {
- base.OnEntry(e);
- if (e.Method.Name.StartsWith("Set"))
- Setter.OnEntry(e);
- }
-
- public override void OnExit(MethodExecutionEventArgs e)
- {
- if (e.Method.Name.StartsWith("Get"))
- Getter.OnExit(e);
- }
-
-
- public override string MethodName
- {
- get { return base.MethodName.Substring(3); }
- }
-
- // Il faut propager les infos OwnerType, Owner, MethodName et Value vers nos objets Getter et Setter car ceux-ci n'interceptent pas directement les méthodes.
- private Get Getter
- {
- get
- {
- if (_Getter == null || (_Getter!=null && _Getter.Owner!=this.Owner))
- _Getter = new Get
- {
- OwnerType = this.OwnerType,
- Owner = this.Owner,
- MethodName = this.MethodName,
- Value = this.Value
- };
- return _Getter;
- }
- }
-
- private Set Setter
- {
- get
- {
- if (_Getter == null || (_Getter!=null && _Getter.Owner!=this.Owner))
- _Setter = new Set
- {
- OwnerType = this.OwnerType,
- Owner = this.Owner,
- MethodName = this.MethodName,
- Value = this.Value
- };
- return _Setter;
- }
- }
- }
-
- /// <summary>
- /// Attribut à associer à une méthode d'extension pour que celle-ci remplace un accesseur "get" d'une propriété.
- /// </summary>
- [Serializable]
- [MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData = true)]
- public class Get : BasePropertyInterceptor
- {
- public override void CompileTimeInitialize(MethodBase method)
- {
- base.CompileTimeInitialize(method);
- // la méthode "Get" doit être sans paramètre.
- if (method.GetParameters().Length != 1)
- throw new Exception(string.Format("Une méthode \"{0}\" portant un attribut \"Get\" a été trouvée, mais elle possède un ou plusieurs paramètres sans modificateur \"this\".", method.Name));
- var instance = method.GetParameters()[0];
-
- // on cherche une methode portée par la même classe, de même nom et possédant un attribut "Set".
- var presumedSetters = method.DeclaringType.GetMethods().Where(m =>
- {
- if (m.Name == method.Name && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString())
- {
- var attrs = m.GetCustomAttributes(typeof(Set), false);
- if (attrs != null && attrs.Length != 0)
- return true;
- }
- return false;
- });
- if (presumedSetters.Count() == 0)
- throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} portant un attribut \"Set\".", method.Name, instance.ParameterType));
- }
-
- public override void OnExit(MethodExecutionEventArgs e)
- {
- e.ReturnValue = PropertyValues[OwnerType, Owner, MethodName];
- }
- }
-
- /// <summary>
- /// Attribut à associer à une méthode d'extension pour que celle-ci remplace un accesseur "set" d'une propriété.
- /// </summary>
- [Serializable]
- [MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData=true)]
- public class Set : BasePropertyInterceptor
- {
- public override void CompileTimeInitialize(MethodBase method)
- {
- base.CompileTimeInitialize(method);
- // on vérifie que la méthode ne possède qu'un seul paramètre.
- if (method.GetParameters().Length != 2)
- throw new Exception(string.Format("La méthode \"{0}\" définie comme accesseur \"set\" doit posséder un unique paramètre sans modificateur \"this\".", method.Name));
- var param = method.GetParameters()[1];
- var instance = method.GetParameters()[0];
-
- // on cherche une methode portée par la même classe, de même nom et possédant un attribut "Get".
- var presumedGetters = method.DeclaringType.GetMethods().Where(m =>
- {
- if (m.Name == method.Name && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString())
- {
- var attrs = m.GetCustomAttributes(typeof(Get), false);
- if (attrs != null && attrs.Length != 0)
- return true;
- }
- return false;
- });
- if(presumedGetters.Count()==0)
- throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} portant un attribut \"Get\".", method.Name, instance.ParameterType));
-
- // la méthode "Get" doit avoir une valeur de retour du même type que le paramètre de la méthode "Set".
- presumedGetters = presumedGetters.Where(m => m.ReturnType == param.ParameterType);
- if (presumedGetters.Count() == 0)
- throw new Exception(string.Format("Une méthode \"{0}\" portant un attribut \"Get\" a été trouvée, mais le type de son paramètre de retour ne correspond pas à celui du paramètre de la méthode \"Set\".", method.Name));
- }
-
- public override void OnEntry(MethodExecutionEventArgs e)
- {
- base.OnEntry(e);
- if (Value == null)
- return;
- if (!PropertyValues.ContainsKey(OwnerType))
- PropertyValues.Add(OwnerType, new Dictionary<object, Dictionary<string, object>>());
- if (!PropertyValues[OwnerType].ContainsKey(Owner))
- PropertyValues[OwnerType].Add(Owner, new Dictionary<string, object>());
- if (!PropertyValues[OwnerType, Owner].ContainsKey(MethodName))
- PropertyValues[OwnerType, Owner].Add(MethodName, Value);
- }
- }
- }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Laos;
using System.Reflection;
using PostSharp.Extensibility;
using System.Text.RegularExpressions;
namespace ExtensionProperties
{
/// <summary>
/// Classe de base pour intercepter les méthodes d'extension "propriétés"
/// </summary>
[Serializable]
public abstract class BasePropertyInterceptor : OnMethodBoundaryAspect
{
protected static PropertyContainer PropertyValues = PropertyContainer.GetInstance();
public override void OnEntry(MethodExecutionEventArgs e)
{
OwnerType = e.Method.GetParameters()[0].ParameterType;
Owner = e.GetArguments()[0];
if (e.GetArguments().Length > 1)
Value = e.GetArguments()[1];
}
public override void CompileTimeInitialize(MethodBase method)
{
MethodName = method.Name;
}
/// <summary>
/// Type de l'objet portant la méthode-"propriété".
/// </summary>
public Type OwnerType { get; set; }
/// <summary>
/// Instance de l'objet portant la méthode-"propriété".
/// </summary>
public object Owner { get; set; }
/// <summary>
/// Nom de la méthode-"propriété".
/// </summary>
public virtual string MethodName { get; set; }
/// <summary>
/// Valeur de la propriété.
/// </summary>
public object Value { get; set; }
[Serializable]
protected class PropertyContainer : Dictionary<Type, Dictionary<object, Dictionary<string, object>>>
{
// Design pattern singleton
private static PropertyContainer instance = null;
private PropertyContainer() { }
public static PropertyContainer GetInstance()
{
if (instance == null)
instance = new PropertyContainer();
return instance;
}
// Redéfinition d'indexeurs
public object this[Type objtype, object obj, string propertyName]
{
get
{
try { return base[objtype][obj][propertyName]; }
catch { return null; }
}
}
public Dictionary<string, object> this[Type objtype, object obj]
{
get
{
try { return base[objtype][obj]; }
catch { return null; }
}
}
}
}
/// <summary>
/// Attribut à associer à la classe contenant les méthodes d'extension. Il intercepte les méthodes d'extension "Get*"/"Set*" et renvoit/stock les valeurs.
/// </summary>
[Serializable]
public class InterceptProperties : BasePropertyInterceptor
{
private Get _Getter;
private Set _Setter;
public override void CompileTimeInitialize(MethodBase method)
{
base.CompileTimeInitialize(method);
if (method.Name.StartsWith("Get"))
{
CheckAccessorAttributes(method);
// la méthode "Get" doit être sans paramètre.
if (method.GetParameters().Length != 1)
throw new Exception(string.Format("Une méthode dont le nom commence par \"Get\" a été trouvée, mais elle possède un ou plusieurs paramètres sans modificateur \"this\".", method.Name));
var instance = method.GetParameters()[0];
// on cherche une methode portée par la même classe, de même nom et possédant un attribut "Set".
var presumedSetters = method.DeclaringType.GetMethods().Where(m => m.Name.StartsWith("Set") && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString());
if (presumedSetters.Count() == 0)
throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} dont le nom commence par \"Set\".", method.Name, instance.ParameterType));
}
if (method.Name.StartsWith("Set"))
{
CheckAccessorAttributes(method);
// on vérifie que la méthode ne possède qu'un seul paramètre.
ParameterInfo param;
if (method.GetParameters().Length != 2)
throw new Exception(string.Format("La méthode \"{0}\" définie comme accesseur \"set\" doit posséder un unique paramètre sans modificateur \"this\".", method.Name));
param = method.GetParameters()[1];
var instance = method.GetParameters()[0];
// on cherche une methode portée par la même classe, de même nom et possédant un attribut "Get".
var presumedGetters = method.DeclaringType.GetMethods().Where(m => m.Name.StartsWith("Get") && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString());
if (presumedGetters.Count() == 0)
throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} dont le nom commence par \"Get\".", method.Name, instance.ParameterType));
// la méthode "Get" doit avoir une valeur de retour du même type que le paramètre de la méthode "Set".
presumedGetters = presumedGetters.Where(m => m.ReturnType == param.ParameterType);
if (presumedGetters.Count() == 0)
throw new Exception(string.Format("Une méthode dont le nom commence par \"Get\" a été trouvée, mais le type de son paramètre de retour ne correspond pas à celui du paramètre de la méthode \"Set\".", method.Name));
}
}
protected void CheckAccessorAttributes(MethodBase method)
{
var setAttr = method.GetCustomAttributes(typeof(Set), false);
var getAttr = method.GetCustomAttributes(typeof(Get), false);
if (setAttr != null && setAttr.Length != 0)
throw new Exception(string.Format("La méthode \"{0}\" ne doit pas avoir d'attribut \"Set\" associé",method.Name));
if (getAttr != null && getAttr.Length != 0)
throw new Exception(string.Format("La méthode \"{0}\" ne doit pas avoir d'attribut \"Get\" associé",method.Name));
}
public override void OnEntry(MethodExecutionEventArgs e)
{
base.OnEntry(e);
if (e.Method.Name.StartsWith("Set"))
Setter.OnEntry(e);
}
public override void OnExit(MethodExecutionEventArgs e)
{
if (e.Method.Name.StartsWith("Get"))
Getter.OnExit(e);
}
public override string MethodName
{
get { return base.MethodName.Substring(3); }
}
// Il faut propager les infos OwnerType, Owner, MethodName et Value vers nos objets Getter et Setter car ceux-ci n'interceptent pas directement les méthodes.
private Get Getter
{
get
{
if (_Getter == null || (_Getter!=null && _Getter.Owner!=this.Owner))
_Getter = new Get
{
OwnerType = this.OwnerType,
Owner = this.Owner,
MethodName = this.MethodName,
Value = this.Value
};
return _Getter;
}
}
private Set Setter
{
get
{
if (_Getter == null || (_Getter!=null && _Getter.Owner!=this.Owner))
_Setter = new Set
{
OwnerType = this.OwnerType,
Owner = this.Owner,
MethodName = this.MethodName,
Value = this.Value
};
return _Setter;
}
}
}
/// <summary>
/// Attribut à associer à une méthode d'extension pour que celle-ci remplace un accesseur "get" d'une propriété.
/// </summary>
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData = true)]
public class Get : BasePropertyInterceptor
{
public override void CompileTimeInitialize(MethodBase method)
{
base.CompileTimeInitialize(method);
// la méthode "Get" doit être sans paramètre.
if (method.GetParameters().Length != 1)
throw new Exception(string.Format("Une méthode \"{0}\" portant un attribut \"Get\" a été trouvée, mais elle possède un ou plusieurs paramètres sans modificateur \"this\".", method.Name));
var instance = method.GetParameters()[0];
// on cherche une methode portée par la même classe, de même nom et possédant un attribut "Set".
var presumedSetters = method.DeclaringType.GetMethods().Where(m =>
{
if (m.Name == method.Name && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString())
{
var attrs = m.GetCustomAttributes(typeof(Set), false);
if (attrs != null && attrs.Length != 0)
return true;
}
return false;
});
if (presumedSetters.Count() == 0)
throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} portant un attribut \"Set\".", method.Name, instance.ParameterType));
}
public override void OnExit(MethodExecutionEventArgs e)
{
e.ReturnValue = PropertyValues[OwnerType, Owner, MethodName];
}
}
/// <summary>
/// Attribut à associer à une méthode d'extension pour que celle-ci remplace un accesseur "set" d'une propriété.
/// </summary>
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData=true)]
public class Set : BasePropertyInterceptor
{
public override void CompileTimeInitialize(MethodBase method)
{
base.CompileTimeInitialize(method);
// on vérifie que la méthode ne possède qu'un seul paramètre.
if (method.GetParameters().Length != 2)
throw new Exception(string.Format("La méthode \"{0}\" définie comme accesseur \"set\" doit posséder un unique paramètre sans modificateur \"this\".", method.Name));
var param = method.GetParameters()[1];
var instance = method.GetParameters()[0];
// on cherche une methode portée par la même classe, de même nom et possédant un attribut "Get".
var presumedGetters = method.DeclaringType.GetMethods().Where(m =>
{
if (m.Name == method.Name && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.ToString() == instance.ParameterType.ToString())
{
var attrs = m.GetCustomAttributes(typeof(Get), false);
if (attrs != null && attrs.Length != 0)
return true;
}
return false;
});
if(presumedGetters.Count()==0)
throw new Exception(string.Format("Imposssible de trouver une méthode \"{0}\" de {1} portant un attribut \"Get\".", method.Name, instance.ParameterType));
// la méthode "Get" doit avoir une valeur de retour du même type que le paramètre de la méthode "Set".
presumedGetters = presumedGetters.Where(m => m.ReturnType == param.ParameterType);
if (presumedGetters.Count() == 0)
throw new Exception(string.Format("Une méthode \"{0}\" portant un attribut \"Get\" a été trouvée, mais le type de son paramètre de retour ne correspond pas à celui du paramètre de la méthode \"Set\".", method.Name));
}
public override void OnEntry(MethodExecutionEventArgs e)
{
base.OnEntry(e);
if (Value == null)
return;
if (!PropertyValues.ContainsKey(OwnerType))
PropertyValues.Add(OwnerType, new Dictionary<object, Dictionary<string, object>>());
if (!PropertyValues[OwnerType].ContainsKey(Owner))
PropertyValues[OwnerType].Add(Owner, new Dictionary<string, object>());
if (!PropertyValues[OwnerType, Owner].ContainsKey(MethodName))
PropertyValues[OwnerType, Owner].Add(MethodName, Value);
}
}
}
Sources du même auteur
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
Héritage multiple [ par zigxag ]
Bonjour !je souhaite faire un héitage multiple en C#, mais je sais très bien que l'on peut pas. Mais alors, comment contourner la contrainte
[C#]Comment faire de l'héritage multiple ? [ par oberown ]
Comment faire pour qu'une classe A hérite de la classe B et C ?
Héritage multiple [ par ricklekebekoi ]
prenons trois classesBaseMorpionGame;BaseTwoPlayerGame;BaseIAGame;Ensuite, deux autres classes:SingleMorpionGame;TwoPJMorpionGame;Je souhaiterais que
migration vb6 vers c# [ par lagoelle ]
Bonjour,Je migre de VB6 à C# et des différences au niveau des controles m'étonne.Par exemple, le label en VB6 a une propriété
datagrid [ par penchu ]
bonjour, je recherche le moyen de cacher une de mes colonnes de ma datagrid en asp, ca va, je la cache dans le code html ou bien je met la proprié
Recuperer le nom d un fichier sans son extension dans un textbox [ par amirirn1 ]
Bonjour,j aimerai recuperer le nom d un fichier que j ai ouvert dans un textbox sans l extension du fichier.aaa.txt je veux textbox.Text = aaa
Protected ou private ? [ par thiosyiasar ]
Protected ou Private ? Salut à tous. En fait j'ai une petite question qui me turlupine un peu depuis quelques temps. J'ai débuté la pro
Word saveAs (changer l extension) [ par amirirn1 ]
SalutJ ai pris un element web Browser de windows que j ai ajouté , j arrive bien à avoir des pages web dessus.Mais ce que j aimerai ,c est d
C# Excel Format de cellule [ par blundle ]
Bonjour,je suis en train de créer un outil d'export permettant présenter les données d'une DB Access dans une feuille MS Excel.Le probl
APP.CONFIG et value multiple [ par winz611 ]
Bonjour,je voudrais alimenter des listbox avec un contenu issu du fichier app.config.Est il possible d'avoir plusieur values pour une seule clé ?
|
Derniers Blogs
[TECHDAYS2012] OUI J'Y SERAI![TECHDAYS2012] OUI J'Y SERAI! par JeremyJeanson
Bonsoir, Certes, je l'annonce avec un peu de retard, mais je serai effectivement au Techdays demain. Comme l'an dernier, je participerai au programme ATE (Ask The Expert). Si vous avez des questions Workflow, WCF, AppFabric ou plus généralement .net, n'hé...
Cliquez pour lire la suite de l'article par JeremyJeanson TFS INTEGRATION TOOLS - SUIVI DES SYNCHRONISATIONS AVEC REPORTING SERVICESTFS INTEGRATION TOOLS - SUIVI DES SYNCHRONISATIONS AVEC REPORTING SERVICES par vfabing
Afin de s'assurer du bon fonctionnement des différentes synchronisations effectuées par les TFS Integration Tools, 2 rapports sont présents dès l'installation. Il suffit alors d'effectuer les manipulations suivantes pour pouvoir les visualiser : Loca...
Cliquez pour lire la suite de l'article par vfabing CSS CONTENT STATE SELECTORS (PERSONNAL DRAFT)CSS CONTENT STATE SELECTORS (PERSONNAL DRAFT) par FREMYCOMPANY
Bonjour à tous, Je viens de publier une proposition comprenant 5 pseudo-classes pour le CSS Working Group ayant trait à l'état de chargement d'un élément (ex: IMG,VIDEO,AUDIO,OBJECT pour l'HTML.). Si le c½ur vous en dit, vous pouvez retrouver cette p...
Cliquez pour lire la suite de l'article par FREMYCOMPANY MBA : POURQUOI FAIRE ET COMMENT LE CHOISIR ?MBA : POURQUOI FAIRE ET COMMENT LE CHOISIR ? par ROMELARD Fabrice
Formation initiale Durant la formation, le découpage classique est le suivant (je donnerai les équivalences Suisse lorsque je les connaîtrais) : Ecole primaire jusqu'au Collège : Formation générale permettant d'obtenir les méthodes...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice Y'A DES ERREURS QUI PEUVENT RENDRE LE DéVELOPPEUR VIOLENTY'A DES ERREURS QUI PEUVENT RENDRE LE DéVELOPPEUR VIOLENT par Aleks
Quand on a ce genre d'erreur sans log :
Et bas on a juste envie de choper le gas de Microsoft qu'a développé ça et lui foutre des baffes de Coboye ! ...
Cliquez pour lire la suite de l'article par Aleks
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|