C# 在c中运行时向类型化对象添加expando属性#

C# 在c中运行时向类型化对象添加expando属性#,c#,garbage-collection,expandoobject,C#,Garbage Collection,Expandoobject,在.net中,是否有任何方法可以在运行时将属性字典绑定到实例,例如,就好像基本对象类具有如下属性: public IDictionary Items { get; } 我提出了一个涉及静态字典和扩展方法的解决方案 void Main() { var x = new object(); x.Props().y = "hello"; } static class ExpandoExtension { static IDictionary<object, dynami

在.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;       
    } 
}
void Main()
{
var x=新对象();
x、 Props().y=“你好”;
}
静态类扩展扩展{
静态IDictionary props=新字典();
公共静态动态道具(此对象键)
{ 
动态o;
如果(!props.TryGetValue(键,输出o)){
o=新的ExpandoObject();
道具[钥匙]=o;
}
返回o;
} 
}
但这会阻止对象获取GC'd,因为props集合持有引用。事实上,对于我的特定用例来说,这是可以的,因为我可以在完成使用道具的特定任务后手动清除道具,但我想知道,在允许垃圾收集的同时,是否有一些巧妙的方法将ExpandoObject绑定到键?

您可以使用引用对象,以便它们仍然可以被垃圾收集。尽管如此,你仍然需要手工清理字典,因为对象本身已被销毁。

请查看字典

ConditionalWeakTable类使语言编译器能够在运行时将任意属性附加到托管对象。ConditionalWeakTable对象是一个字典,它将托管对象(由键表示)绑定到其附加属性(由值表示)。对象的键是特性附着到的TKey类的各个实例,其值是指定给相应对象的特性值

本质上,它是一个字典,其中键和值都是弱引用的,并且只要键处于活动状态,值就会保持活动状态


静态类扩展扩展
{
私有静态只读条件weaktable道具=
新的条件weaktable();
公共静态动态道具(此对象键)
{ 
返回props.GetOrCreateValue(键);
} 
}

我对此进行了研究,但离开时认为一定有更简单的方法!在上面的示例中,我们必须能够使用x找到ExpandoObject,但不能在props字典中实际存储x。为了解决这个问题,我考虑使用Dictionary,通过执行GetHashcode()来存储内容,然后在列表中搜索包含键对象弱引用的动态。不太好,Expandos仍然没有得到GC'd。我想出了一个办法Dictionary@mcintyre321当前位置看起来你很幸运,有人已经为你实现了你的字典功能。我必须承认我不知道这个存在。
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);       
    } 
}