代码之家  ›  专栏  ›  技术社区  ›  Thomas Levesque

向动态对象动态添加成员

  •  8
  • Thomas Levesque  · 技术社区  · 16 年前

    我正在寻找一种将成员动态添加到动态对象的方法。好吧,我想需要澄清一下…

    当你这样做的时候:

    dynamic foo = new ExpandoObject();
    foo.Bar = 42;
    

    这个 Bar 属性将在运行时动态添加。但是代码仍然“静态”地指向bar(名称“bar”是硬编码的)。如果我想在运行时添加一个属性而不在编译时知道它的名称怎么办?

    我知道如何使用自定义动态对象(实际上 blogged about it 几个月前),使用 DynamicObject 上课,但是我怎么做呢 任何 动态对象?

    我可能会用 IDynamicMetaObjectProvider 接口,但我不理解如何使用它。例如,我应该把什么论点传给 GetMetaObject 方法?(期待一个 Expression )

    顺便问一下,如何对动态对象执行反射?”常规反射和 TypeDescriptor 不显示动态成员…

    任何见解都将受到赞赏!

    4 回复  |  直到 11 年前
        1
  •  9
  •   Dino Viehland    16 年前

    您想要的类似于python的getattr/setattr函数。在C或VB.NET中,没有类似的内置方式来实现这一点。DLR的外层(随Microsoft.scripting.dll中的Ironpython和IronRuby一起提供)包含一组托管API,其中包含一个具有getmember/setmember方法的ObjectOperations API。您可以使用这些,但是您需要额外依赖于DLR和基于DLR的语言。

    最简单的方法可能是用现有的C粘合剂创建一个Callsite。您可以通过查看ildasm或reflector中“foo.bar=42”的结果来获得此代码。但一个简单的例子是:

    object x = new ExpandoObject();
    CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
                Binder.SetMember(
                    Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
                    "Foo",
                    null,
                    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
                )
            );
    site.Target(site, x, 42);
    Console.WriteLine(((dynamic)x).Foo);
    
        2
  •  5
  •   Uffe Seerup    14 年前

    expandoobject实现IDictionary<字符串、对象>,尽管是显式的。这意味着您可以简单地将expandoobject强制转换为idictionary<string、object>并操作字典。

    dynamic foo = new ExpandoObject();
    foo.Bar = 42;
    food = (IDictionary<string,object>)foo;
    food["Baz"] = 54
    
        3
  •  5
  •   jbtule    12 年前

    开源框架 Dynamitey 将执行此操作(可通过 nuget )它在仍然缓存@dino viehland使用的调用站点和绑定器代码的同时进行封装。

    Dynamic.InvokeSet(foo,"Bar",42);
    

    也可以叫很多人 other kinds of c# binder too .

        4
  •  1
  •   JoBot    13 年前

    我知道这是一个相当古老的职位,但我想我会过去的 Miron Abramson solution 关于如何在运行时创建自己的类型和添加属性——以防其他人正在寻找类似的东西。