Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

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?

share|improve this question
    
Reflection is probably your own solution, unless you put your properties into a hashmap so they can be determined at runtime. – James Black Jun 13 '10 at 18:37
    
possible duplicate of Adding unknown (at design time) properties to an ExpandoObject – nawfal Jul 19 '14 at 15:57
up vote 11 down vote accepted

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.

share|improve this answer
    
Thanks Marc - I thought I'd been missing something obvious but obviously not! :) Have you got any links to a good example of how to do code emission so I can give this a go? If I can get it going this looks like something work sharing! – Kieran Benton Jun 13 '10 at 19:30
    
@Kieran - it depends what you need. It didn't sound like you needed emission (the code I posted was just a sample of how ugly it is). – Marc Gravell Jun 13 '10 at 23:16
    
Downvoted because this did not explain that an expandoObject uses a dictionary as its backing store and can be used exactly as the OP originally suggested. There is no need for reflection OR emit on an expandoObject. That said @MarcGravell is correct that for non-expando dynamic objects (as well as regular objects assigned to a dynamic var) there isn't a clean solution. – Andrew Hanlon Feb 13 '12 at 18:37
1  
@ach actually, I do now have a clean solution for this: FastMember. Will edit it in... – Marc Gravell Feb 13 '12 at 18:41
    
@ach re your downvote: please read the question: "ExpandoObject is just used as an example, this could be any class that implements IDynamicMetaObjectProvider" - it would be entirely incorrect for me to focus on ExpandoObject as a dictionary. – Marc Gravell Feb 13 '12 at 18:44

Paul Sasik answered a similar question at C# 4.0 Dynamic vs Expando... where do they fit ?

using System;
using System.Dynamic;

class Program
{
    static void Main(string[] args)
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;
        p["A"] = "New val 1";
        p["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}
share|improve this answer

My open source framework Dynamitey has methods for invoking based on string names using the DLR. It does the work of caching binding sites and streamlines it down to one method call. it also runs faster than reflection on non-dynamic objects too.

Dynamic.InvokeSet(e, "TestKey", "value");
share|improve this answer

To add to Jonas' answer, you don't have to create a new var p. Use this approach instead:

using System;
using System.Dynamic;

class Program
{
    static void Main(string[] args)
    {
        dynamic expando = new ExpandoObject();
        ((IDictionary<String, object>)expando)["A"] = "New val 1";
        ((IDictionary<String, object>)expando)["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}
share|improve this answer

fast-member may fit the bill - it looks like it generates the IL on the fly, but caches it so it's really fast after the first use.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.