How to set a property of a C# 4 dynamic object when you have the name in another variable

后端 未结 5 596
独厮守ぢ
独厮守ぢ 2021-02-01 13:38

I\'m looking for a way to modify properties on a dynamic C# 4.0 object with the name of the property known only at runtime.

Is there a way to do something l

5条回答
  •  野性不改
    2021-02-01 14:09

    Not very easily, no. Reflection doesn't work, since it assumes a regular type model, which is not the full range of dynamic. If you are actually just talking to regular objects, then just use reflection here. Otherwise, I expect you may want to reverse-engineer the code that the compiler emits for a basic assignment, and tweak it to have a flexibly member-name. I'll be honest, though: this isn't an attractive option; a simple:

    dynamic foo = ...
    foo.Bar = "abc";
    

    translates to:

    if (
    o__SiteContainer0.<>p__Site1 == null) {
    o__SiteContainer0.<>p__Site1 = CallSite>.Create(Binder.SetMember(CSharpBinderFlags.None, "Bar", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) })); }
    o__SiteContainer0.<>p__Site1.Target(
    o__SiteContainer0.<>p__Site1, foo, "abc");

    If you want an approach that works for both dynamic and non-dynamic objects: FastMember is handy for this, and works at either the type or object level:

    // could be static or DLR 
    var wrapped = ObjectAccessor.Create(obj); 
    string propName = // something known only at runtime 
    Console.WriteLine(wrapped[propName]);
    

    available on Nuget, and heavily optimised for both dynamic and non-dynamic scenarios.

提交回复
热议问题