Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 like (ExpandoObject is just used as an example, this could be any class that implements IDynamicMetaObjectProvider):

string key = "TestKey"; dynamic e = new ExpandoObject(); e[key] = "value"; 

Which would be equivalent to:

dynamic e = new ExpandoObject(); e.TestKey = "value"; 

Or is the only way forward reflection?

like image 348
Kieran Benton Avatar asked Jun 13 '10 18:06

Kieran Benton


People also ask

What is AC property?

A C# property have two accessors, get property accessor and set property accessor. A get accessor returns a property value, and a set accessor assigns a new value. The value keyword represents the value of a property. Properties in C# and . NET have various access levels that is defined by an access modifier.

How do you declare a property?

To declare properties, add a static properties getter to the element's class. The getter should return an object containing property declarations. Attribute type, used for deserializing from an attribute. Polymer supports deserializing the following types: Boolean , Date , Number , String , Array and Object .

How do I set default value in property?

Right-click the control that you want to change, and then click Properties or press F4. Click the All tab in the property sheet, locate the Default Value property, and then enter your default value. Press CTRL+S to save your changes.

How do you call a property in C#?

In c# properties, the get accessor will be invoked while reading the value of a property, and when we assign a new value to the property, then the set accessor will be invoked by using an argument that provides the new value.


1 Answers

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 (<Main>o__SiteContainer0.<>p__Site1 == null) {     <Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "Bar", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } <Main>o__SiteContainer0.<>p__Site1.Target(<Main>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.

like image 122
Marc Gravell Avatar answered Sep 21 '22 00:09

Marc Gravell