9

Yes, title sounds a bit confusing, so I'll explain what I mean: suppose you have a C# 4.0 'dynamic' object, and the name of a property. How would you retrieve that property from the dynamic object?

In other words, how would you implement:

public static object GetDynamicValue(dynamic o, string name) { ... }

Another way to put it is that I'm trying to treat a dynamic object as an IDictionary.

Note that reflection is likely not an option here, since the dynamic object could be a custom implementation which is not reflection based (e.g. by extending DynamicObject and doing its own thing).

1
  • 1
    Can you tell a little bit more about your use case? If you want to have a dynamic object that is similar to IDictionary, why not use ExpandoObject, for example? Jon's suggestion probably works, but I have a feeling that this is a too complicated solution for what you are trying to do. Commented Dec 18, 2009 at 18:56

2 Answers 2

14

You would have to build a call site, create a binder etc.

The easiest way to see what happens is to compile this:

public static object GetDynamicValue(dynamic o, string name)
{
    return o.Foo;
}

Then decompile it with Reflector and work out what it's doing. It'll be pretty complicated, mind you - and you'll need to change it from being a single, static, cached call site to creating a new one on each invocation.

Here's an example which does work... but whether it's entirely correct or not is a different matter :) (I got this going by doing exactly what I suggested above.)

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Dynamic;
using System.Runtime.CompilerServices;

class Test
{
    public static object GetDynamicValue(dynamic o, string name)
    {
        CallSite<Func<CallSite, object, object>> site 
            = CallSite<Func<CallSite, object, object>>.Create
            (Binder.GetMember(CSharpBinderFlags.None, name, 
             typeof(Test), new CSharpArgumentInfo[] 
             { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
        return site.Target(site, o);
    }

    static void Main()
    {
        Console.WriteLine(GetDynamicValue("hello", "Length"));
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Very nice, thanks Jon! That brings a lot of concepts that I haven't dealt with, so I'll need to study it carefully. It feels strange that typeof(Test) is used in there, since it should be of no relevance. But I tried setting it to null and the code still works, so apparently it wasn't doing much.
It's relevant in terms of what members are accessible - you'll be able to get at private members of Test using this code, but not private members of other types.
3

The Open source framework ImpromptuInterface (available in nuget) does this, and does the extra work involved because caching the call site is important for performance.

See InvokeGet

public static object GetDynamicValue(dynamic o, string name) {
        return Impromptu.InvokeGet(o,name);
}

1 Comment

@David-Ebbo While Clay allows you to access it's own properties via string name, InvokeGet allows you to access ANY IDynamicMetaObjectProvider properties via string name (or any regular object faster that reflection)...unless I am missing something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.