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
UNE JOLIE-HORLOGE ET PAS QU'UN PEU !UNE JOLIE-HORLOGE ET PAS QU'UN PEU ! par neodante
Pour les possesseurs d'iPhone, ça y est Bijin Tokei - qui se traduit littéralement en Français par " Jolie Horloge " - est arrivé et GRATUITEMENT s'il vous plaît ! Après la version Tokyo, Hokkaido, night club, racing, Gal, "pour les mademoiselles'", . voi...
Cliquez pour lire la suite de l'article par neodante TECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICESTECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICES par ROMELARD Fabrice
Animé par: Gaetan Bouveret et Julien Chomarat Business Connectivity Services (BCS) est dans SharePoint 2010 la version 2 de Business Data Catalog (BDC dans SharePoint 2007). Il s'agit de la solution permettant de visualiser des données provenan...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice [DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE par orion
Comme de nombreux geek, je suis un grand amateur de série TV et je rate régulièrement des épisodes de mes séries préférés. Une solution s'offre à vous avec ce merveilleux site : Tv Gorge - www.tvgorge.com Moteur de recherche à l'appui, vous pouvez ...
Cliquez pour lire la suite de l'article par orion TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|