Добавление свойств расширения в типизированный объект во время выполнения в C#

Есть ли в.net способ привязать словарь свойств к экземпляру во время выполнения, т. Е. Как если бы класс базового объекта имел свойство, подобное:

public IDictionary Items { get; }

Я пришел с решением, включающим статический словарь и метод расширения

void Main()
{
    var x = new object();
    x.Props().y = "hello";
}

static class ExpandoExtension {
    static IDictionary<object, dynamic> props = new Dictionary<object, dynamic>();
    public static dynamic Props(this object key)
    { 
        dynamic o;
        if (!props.TryGetValue(key, out o)){
            o = new ExpandoObject();
            props[key] = o;
        }
        return o;       
    } 
}

но это мешает объектам получать GC'd, так как коллекция props содержит ссылку. На самом деле, это почти нормально для моего конкретного случая использования, так как я могу очистить опоры вручную, как только я закончу с конкретной вещью, для которой я их использую, но мне интересно, есть ли какой-нибудь хитрый способ связать ExpandoObject к ключу при разрешении сбора мусора?

2 ответа

Решение

Посмотрите на класс ConditionalWeakTable;.

Класс ConditionalWeakTable позволяет языковым компиляторам присоединять произвольные свойства к управляемым объектам во время выполнения. Объект ConditionalWeakTable - это словарь, который связывает управляемый объект, представленный ключом, со своим присоединенным свойством, которое представлено значением. Ключи объекта - это отдельные экземпляры класса TKey, к которому присоединено свойство, а его значения - это значения свойств, которые назначены соответствующим объектам.

По сути, это словарь, в котором на ключи и значения слабо ссылаются, а значение сохраняется, пока ключ жив.


static class ExpandoExtensions
{
    private static readonly ConditionalWeakTable<object, ExpandoObject> props =
        new ConditionalWeakTable<object, ExpandoObject>();

    public static dynamic Props(this object key)
    { 
        return props.GetOrCreateValue(key);       
    } 
}

Вы можете использовать WeakReference для ссылки на объекты, чтобы они все еще могли собираться мусором. Вы все равно должны будете очистить свой словарь вручную, так как сами объекты уничтожены.

Другие вопросы по тегам