Préservation de l’état dans une méthode d’extension

L’équipe C # a déjà envisagé d’append des propriétés d’extension, des événements, etc. à C #.

Par Eric Lippert:

http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx

Cependant, pour que ces fonctionnalités soient utiles, elles doivent pouvoir stocker un nouveau type d’état avec un object. Il semble que la seule façon de procéder serait d’utiliser un dictionnaire et d’associer chaque instance d’un object à l’état supplémentaire.

Il serait utile de pouvoir copier cette fonctionnalité “manuellement” en créant mon propre dictionnaire (et peut-être des méthodes d’extension / définition). Cependant, pour associer une instance particulière d’un object à un état, vous devez hacher la référence réelle à l’object. Dans une autre langue, vous pouvez le faire en hachant son emplacement de mémoire. Toutefois, en C #, il n’est pas garanti de restr constant, et l’utilisation de code non sécurisé pour réaliser cette fonctionnalité est loin d’être idéale.

Est-ce que quelqu’un sait s’il est possible d’obtenir une référence aléatoire à un object qui ne change pas lorsque l’état interne de l’object change? Il existe évidemment un mécanisme interne permettant de garder la trace d’objects individuels, quel que soit leur emplacement de mémoire, mais je ne suis pas sûr que cela soit exposé au code utilisateur.

Remarque: le simple fait de hacher l’object lui-même ne fonctionnera pas du tout, car GetHashCode () dépend de l’état interne d’un object et non de l’ object en question.

Merci pour toute idée.

Vous recherchez la classe ConditionalWeakTable .

** ENSEMBLE ANSWEr EDITED ** Les propriétés sont conservées dans un dictionnaire qui utilise une référence faible aux objects en tant que clés et un dictionnaire avec des paires object-chaîne pour stocker les propriétés et leurs valeurs.

Pour définir, obtenir ou supprimer les propriétés d’un object, l’object est recherché dans les références faibles du dictionnaire.

Il pourrait y avoir deux manières de se débarrasser des propriétés non utilisées:

  • vérifier l’isAlive de la référence faible et supprimer l’entrée dans le dictionnaire si false
  • implémentez IDisposable dans les objects “extensibles” et appelez une méthode d’extension qui supprime les propriétés de l’object en cours de suppression.

J’ai inclus un bloc optionnel using dans l’exemple de code afin que vous puissiez déboguer et voir comment Dispose appelle la méthode d’extension RemoveProperties . Ceci est bien sûr facultatif, et la méthode serait appelée lorsque l’object est GCé.

Échantillon de travail de l’idée utilisant WeakReference, Dictionnaires statiques et IDisposable.

 using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication3 { class Program { static void Main(ssortingng[] args) { using (PropertyLessClass plc = new PropertyLessClass()) { plc.SetProperty("age", 25); plc.SetProperty("name", "John"); Console.WriteLine("Age: {0}", plc.GetProperty("age")); Console.WriteLine("Name: {0}", plc.GetProperty("name")); } Console.ReadLine(); } } } public class PropertyLessClass : IDisposable { public void Dispose() { this.DeleteProperties(); } } public static class PropertyStore { private static Dictionary> store = new Dictionary>(); public static void SetProperty(this object o, ssortingng property, object value) { var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o); if (key == null) { key = new WeakReference(o); store.Add(key, new Dictionary()); } store[key][property] = value; } public static object GetProperty(this object o, ssortingng property) { var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o); if (key == null) { return null; // or throw Exception } if (!store[key].ContainsKey(property)) return null; // or throw Exception return store[key][property]; } public static void DeleteProperties(this object o) { var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o); if (key != null) { store.Remove(key); } } }