Dynamically adding members to a dynamic object

前端 未结 4 1385
野性不改
野性不改 2020-12-05 21:07

I\'m looking for a way to add members dynamically to an dynamic object. OK, I guess a little clarification is needed...

When you do that :

dynamic fo         


        
相关标签:
4条回答
  • 2020-12-05 21:44

    I know this is quite an old post, but I thought I'd pass along Miron Abramson solution on how you can create your own type and add properties at runtime -- in case anyone else out there is looking for something similar.

    0 讨论(0)
  • 2020-12-05 21:50

    ExpandoObject implements IDictionary<string,object> albeit explicitly. What this means is that you can simply cast the ExpandoObject to IDictionary<string,object> and manipulate the dictionary.

    dynamic foo = new ExpandoObject();
    foo.Bar = 42;
    food = (IDictionary<string,object>)foo;
    food["Baz"] = 54
    
    0 讨论(0)
  • 2020-12-05 21:51

    The opensource framework Dynamitey will do this (available via nuget). It encapsulates while still caching the call site and binder code that @Dino-Viehland used.

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

    It can also call many other kinds of c# binder too.

    0 讨论(0)
  • 2020-12-05 21:55

    What you want is similar to Python's getattr/setattr functions. There's no built in equivalent way to do this in C# or VB.NET. The outer layer of the DLR (which ships w/ IronPython and IronRuby in Microsoft.Scripting.dll) includes a set of hosting APIs which includes an ObjectOperations API that has GetMember/SetMember methods. You could use those but you'd need the extra dependency of the DLR and a DLR based language.

    Probably the simplest approach would be to create a CallSite w/ one of the existing C# binders. You can get the code for this by looking at the result of "foo.Bar = 42" in ildasm or reflector. But a simple example of this would be:

    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);
    
    0 讨论(0)
提交回复
热议问题