Est-ce que vous savez comment s'appelle ce composant ?
Accessoirement, est-il disponible par défaut dans Visual Studio Express 2008 (je ne l'ai pas trouvé), ou bien est-il possible de l'obtenir quelque part, ou bien rien de tout ça ?
Merci ^^
Zephyr (./13) :J'étais tombé sur exactement le même problème, et après recherche sur le net, apparemment il n'existe pas d'équivalent .NET aux pointeurs sur les objets
Le problème c'est que pour ça il me faut conserver une référence vers la variable en question, mais que le mot-clé "ref" du C# se limite aux paramètres des fonctions.
Zephyr (./13) :Oué enfin pour le coup ton SetValue n'est pas sensé accepter un string (ça devrait générer une exception de cast) alors que le ConvertFrom si, donc ça serait plus propre de l'utiliser
Bon, faute de mieux je suis parti sur la solution du ./12
J'aurais besoin de créer un objet, disons "Modifier", qui prenne en paramètre une référence vers une variable (ou un attribut) et qui soit capable par la suite de modifier cette variable. Le détail c'est que par "modifier" je ne parle pas d'appeler ses méthodes et autres, mais bien de remplacer la valeur de la variable. Le problème c'est que pour ça il me faut conserver une référence vers la variable en question, mais que le mot-clé "ref" du C# se limite aux paramètres des fonctions.
Certes il y a bien des pointeurs, mais c'est "unsafe" et j'ai cru comprendre qu'il fallait prendre pas mal de précautions pour éviter que la CLR ne modifie les adresses lors d'un passage du GC.Ce truc s'appelle le pinning (je laisse aux lecteurs le loisir de traduire en fr) et en C# c'est pas bien compliqué, ça se fait avec un petit coup de fixed( ... ) {}, et en dehors de ça, le code usafe fonctionne très bien avec des paramètres de sécurité normaux, il faut juste éviter de l'utiliser quand ce n'est pas nécessaire.
En C++ ça serait très facile : il suffirait que "myRef" soit de type "T&" et qu'il soit initialisé dans le constructeur de "Modifier". Mais en C# la seule solution que j'ai trouvée consiste à passer à "Modifier" non pas une référence vers la variable mais deux delegates (un setter et un getter). Ça marche très bien mais ça m'oblige à déclarer deux méthodes pour chaque variable que je veux "Modifier"-er (voilà ce que ça donne) : très lourd.Fais toi un listing des façons différentes accéder à une valeur dans un type en C#... Tu t'apercevras que la liste n'est pas si longue que ça.
Y-a-t'il moyen de faire autrement ?
public class PropertyModifier { object toModify; public PropertyModifier(object toModify) { this.toModify = toModify; } public void Modify(string property, object value) { FieldInfo fi = this.toModify.GetType().GetField(property, BindingFlags.Instance | BindingFlags.NonPublic); if (fi != null && fi.FieldType == value.GetType()) fi.SetValue(this.toModify, value); } }
sealed class Modifier<T> { delegate T GetTDelegate(); delegate void SetTDelegate(T value); GetTDelegate get; SetTDelegate set; public Modifier(object obj, PropertyInfo property) { if (!(property.CanRead && property.CanWrite)) throw new InvalidOperationException(); get = (GetTDelegate)Delegate.CreateDelegate(typeof(GetTDelegate), obj, property.GetGetMethod()); set = (SetTDelegate)Delegate.CreateDelegate(typeof(GetTDelegate), obj, property.GetSetMethod()); } public T Get() { return get(); } public void Set(T value) { set(value); } }
GoldenCrystal (./20) :
Une propriété autogénérée c'est une propriété où les accesseurs get/set sont générés automatiquement
Sinon je peux te montrer l'approche DynamicMethod qui crée dynamiquement le get/set mais qui est un peu plus lourde à l'initialisation (et aussi rapide pour le reste du temps), mais quoi qu'il en soit ça sera toujours mieux que de la réflexion pure. (Enfin le code qu'a posté yAro peut être un peu optimisé quand même, notamment avec des TypedReference ^^)
Zephyr (./21) :Plus exactement tu lui dis juste je veux une propriété "Length" avec un get et un set (oui sans un set elle te sert a rienGoldenCrystal (./20) :Donc en gros tu dis ".Length est la propriété liée à l'attribut .length" et il te crée automatiquement les get/set par défaut (ceux qui renvoient/modifient directement l'attribut sans pré/post traitement) ?
Une propriété autogénérée c'est une propriété où les accesseurs get/set sont générés automatiquement
Si c'est ça c'est vraiment inutile, créer des propriétés n'a plus aucun sens et autant tout mettre en public directement ^^
Heu, donc voilà la solution la plus polyvalente:Sinon je peux te montrer l'approche DynamicMethod qui crée dynamiquement le get/set mais qui est un peu plus lourde à l'initialisation (et aussi rapide pour le reste du temps), mais quoi qu'il en soit ça sera toujours mieux que de la réflexion pure. (Enfin le code qu'a posté yAro peut être un peu optimisé quand même, notamment avec des TypedReference ^^)
Oh bah si t'as ça sous la main envoie, je sais pas si je l'utiliserai mais par curiosité ça m'intéresse quand même ^^
GoldenCrystal (./23) :
Plus exactement tu lui dis juste je veux une propriété "Length" avec un get et un set (oui sans un set elle te sert a rien) et il crée en interne un champ associé (auquel tu ne peux pas accéder) + get/set par défaut qui font rien (ce qui ne t'empêche en rien d'en faire plus tard une vraie propriété si le besoin s'en ressent)
Bah non ça encapsule quand même ton champ, et je te rappelle que tu peux avoir des modificateurs d'accès différents sur le get et le set, et que ta propriété n'a aucune obligation d'être publique, donc bah voilà quoi
Bon, ok donc voilà la solution la plus polyvalente:Fichier joint : FieldModifier.zipC'est tout bidon mais à l'heure actuelle je pense qu'on ne peut pas faire plus efficace (Il faut garder à l'esprit que tout ça fonctionne sans aucun bidouillage de mémoire et que tout est parfaitement géré par le Garbage Collector)
GoldenCrystal (./29) :
Hmm, fais attention, une simple chaîne de caractères ne permet pas d'identifier un membre de manière suffisamment claire et précise, et tu perds la possibilité d'affiner la description de ce que tu recherches comme ça ^^(Particulièrement, je ne suis plus certain que ça te permette (par exemple) d'obtenir les membres privés si tu ne lui demandes pas explicitement, mais tu t'en rendras vite compte si ce n'est pas le cas.)
Sinon juste une petite note annexe, fais bien attention à ce que tu utilises quand tu codes, car les fonctionnalités "avancées" de C# et/ou du CLR peuvent restreintes plus ou moins fortement par des paramètres de sécurité. (Qui empêcheraient l'utilisation de code unsafe ou limiteraient la réflexion aux membres publics par exemple)ça ne gênera pas si tu code pour toi même ou pour n'importe quel utilisateur maître de sa machine, mais en dehors de ça il faut tenir compte des paramètres de sécurité, et de leur fonctionnement. (Personellement, j'ai toujours du mal à comprendre le fonctionnement de la sécurité .NET, mais il faut au moins savoir qu'elle est là ^^)