Вопрос по state, dictionary, c#, extension-methods, reference – Сохранение состояния в методе расширения
Команда C # ранее рассматривала возможность добавления свойств расширения, событий и т. Д. В C #.
Пер Эрик Липперт:
http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx
Однако для того, чтобы эти функции были полезны, они должны были бы иметь возможность хранить какой-то новый тип состояния с объектом. Кажется, что единственный способ сделать это - использовать словарь и связать каждый экземпляр объекта с каким-либо дополнительным состоянием.
Было бы полезно, если бы можно было скопировать эту функцию "вручную" создав свой собственный словарь (и, возможно, получить / установить методы расширения). Однако для того, чтобы связать определенныйinstance объекта с некоторым состоянием, вам нужно будет хешировать фактическоеreference к объекту. На другом языке вы могли бы сделать это, хэшируя место в памяти, однако в C # это не гарантируется постоянным, и использование небезопасного кода для реализации этой функции в любом случае далеко от идеала.
Кто-нибудь знает, возможно ли получить некоторую хешируемую ссылку на объект, которая не изменяется при изменении внутреннего состояния объекта? Очевидно, существует некоторый внутренний механизм для отслеживания отдельных объектов независимо от их местоположения в памяти, но я не уверен, что на него воздействует пользовательский код.
Примечание: простое хеширование самого объекта вообще не будет работать, поскольку GetHashCode () зависит от того, не находится ли внутреннее состояние объектаwhich object это.
Спасибо за понимание.
Свойства хранятся в словаре, который использует слабые ссылки на объекты в качестве ключей, и словарь с парами строк-объектов для хранения свойств и их значений.
Чтобы установить, получить или удалить свойства для объекта, поиск объекта осуществляется по слабым ссылкам в словаре.
Там может быть два способа избавиться от неиспользуемых свойств:
check the IsAlive of the weak reference, and remove the entry in the dictionary if false implement IDisposable in the "extendable" objects and call an extension method that removes the properties on the object being disposed.Я включил необязательный блок using в пример кода, чтобы вы могли отладить и посмотреть, как Dispose вызываетRemoveProperties
метод расширения. Это, конечно, необязательно, и метод вызывается, когда объект является GC-ed.
Рабочий образец идеи с использованием WeakReference, статических словарей и IDisposable.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] 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<WeakReference, Dictionary<string, object>> store
= new Dictionary<WeakReference, Dictionary<string, object>>();
public static void SetProperty(this object o, string 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<string, object>());
}
store[key][property] = value;
}
public static object GetProperty(this object o, string 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);
}
}
}
IEqualityComparer<WeakReference>
.
PluralizationService
учебный класс