3

I have a dynamic variable

dynamic d = GetSomeObject();

Sometime , in future, a user send me a function to execute ( its name) e.g "UsersGetAll"

So I need to do something like : d.UsersGetAll()

I can do it with reflection. But I want to use the DLR .

Does the only solution of doing this is to have MyObject inherit from DynamicObject and then implement TryInvokeMember?

What if I don't have control over the class ?

1
  • What is the reason for wanting to use the DLR? AFAIK the dynamic language feature was intended for simplification of known method calls on unknown objects. Maybe generate code for compilation by Roslyn at runtime? Commented Nov 28, 2012 at 14:09

2 Answers 2

1

As Jon notes, the following really only applies if you suspect that the type is providing the method at runtime via the DLR; in most simple cases, reflection will be easier.

dynamic is intended when you know the method name but not the target. If you don't know the method name it is tricker. The tricky bit, perhaps, is ensuring you keep the call-site so that it can be re-used (which is how the DLR maintains performance). One cheeky way would be a static utility class that keeps track of invoked methods. Here's an example - note that it gets much messier if you need to handle parameters:

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
    public object Bar() { return "I was here"; }
}
static class Program
{
    static void Main()
    {
        object obj = new Foo();
        object result = DynamicCallWrapper.Invoke(obj, "Bar");
        Console.WriteLine(result);
    }
}

static class DynamicCallWrapper
{
    // Hashtable has nice threading semantics
    private static readonly Hashtable cache = new Hashtable();
    public static object Invoke(object target, string methodName)
    {
        object found = cache[methodName];
        if (found == null)
        {
            lock (cache)
            {
                found = cache[methodName];
                if(found == null)
                {
                    cache[methodName] = found = CreateCallSite(methodName);
                }
            }
        }
        var callsite = (CallSite<Func<CallSite, object,object>>)found;
        return callsite.Target(callsite, target);
    }
    static object CreateCallSite(string methodName)
    {
        return CallSite<Func<CallSite, object, object>>.Create(
            Binder.InvokeMember(
            CSharpBinderFlags.None, methodName, null, typeof(object),
            new CSharpArgumentInfo[] {
                CSharpArgumentInfo.Create(
                     CSharpArgumentInfoFlags.None, null) }));

    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

I can do it with reflection. But I want to use the DLR.

Why? Assuming this is a "normal" object which isn't actually going to respond dynamically, reflection is going to be the easiest approach here.

The dynamic feature in C# 4 (in terms of the language feature) does absolutely nothing to help you here. It only allows dynamic binding of member names within C# source code.

Now you could:

  • Start an IronPython session, and create a tiny Python script to call the method using dynamic binding.
  • Use CSharpCodeProvider to compile some C# code using dynamic with the relevant method name, then execute that code.
  • Look at the generated code for your d.UsersGetAll() call, and basically emulate that.

All of these options are likely to be harder than reflection, if all you want it so call a "normal" method on a "normal" object, and you happen to only know the name at execution time.

Comments

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.