0

I was wondering if it was possible to call a function on a dynamic c# object via a string. I want to do something like this:

string lMethodName = "MethodName";
dynamic lDynamicObject = GetDynamicObject();
lDynamicObject.Invoke(lMethodName, lParameters);

Any thoughts or solutions would be greatly appreciated.

Maybe like Servy said there's a better way to achieve what we want through a different design. We're using SignalR and have a dashboard web app. We want each widget inside the dashboard to have the ability to have data pushed to it. To achieve this we were going to use razor code to inject the widget id into each individual widgets SignalR clientside proxy. Each widget would have something like the following:

hub.client.updateWidget123456 = aUpdateFunction;

Where 123456 is the id of the widget. On the serverside SignalR hub code we could call back into the clientside javascript function:

int lWidgetId = 123456;
dynamic lDynamic = Clients.All;
lDynamic.Invoke("updateWidget" + lWidgetId, lParameters);

There are other ways I can think of to implement this without creating the javascript proxy methods. I thought this was nice because the server had a direct communication line with each individual widget. Which could be accessed from multiple dashboards/browsers but they would all get updated via the single call above.

We could implement this instead by calling some other object in our javascript clientside code who knew about all the widgets and how to direct information to them. I felt like this went against the hub architecture of SignalR and like we were reinventing the wheel by doing this.

Does anyone have any thoughts on a better design approach? Thanks for the help and thanks for your comment Servy for sparking this discussion.

Also, this question is not a duplicate. The other question is not with regards to dynamic objects like Paul commented on below.

Adam
  • 255
  • 1
  • 3
  • 17
  • dup: http://stackoverflow.com/questions/540066/calling-a-function-from-a-string-in-c-sharp – dotNET Apr 18 '13 at 18:43
  • 1
    No, this question is for dynamic types, the other question was for reflection in general. – Paul Apr 18 '13 at 18:46
  • 1
    You almost certainly don't want to be doing this. You should *strongly* consider re-designing your code such that you don't need to do this. – Servy Apr 18 '13 at 19:03
  • 1
    This question isn't a duplicate at all since the other question mentioned here doesn't adress dynamic. It was about static types and reflection and @Paul already commented on that. – pescolino Apr 19 '13 at 18:01
  • 1
    It is true that *IF* you use reflection it is no different, but the OP and likely some who might find this question in the future are trying to do something 'dynamic', and decided for whatever reason that the dynamic keyword might be the answer. Explicit reflection is only one type of solution and an explanation of exactly what the difference is, which is what the accepted answer does, is useful. The linked question predates the introduction of the dynamic keyword by over a year, which first appeared in VS2010. – Paul Apr 19 '13 at 20:01

4 Answers4

2

You can only use reflection to invoke a method on a dynamic if you know that it is an ordinary C# object (i.e. no special runtime binder).

Consider the following class that implements a property bag that can be used dynamically:

public class PropertyBag : DynamicObject
{
    private Dictionary<string, object> _propertyBag = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _propertyBag.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _propertyBag[binder.Name] = value;
        return true;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return base.GetDynamicMemberNames();
    }
}

It is perfectly valid to do the following:

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow";
propertyBag.Value = 42;

If however you try to get the PropertyInfo for any of these dynamic properties it will fail because the PropertyBag class does not implement them:

public static void SetProperty(dynamic propertyBag, string propertyName, object value)
{
    PropertyInfo property = propertyBag.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
    if (property == null)
    {
        throw new NotImplementedException();
    }

    MethodInfo setProperty = property.GetSetMethod();
    setProperty.Invoke(propertyBag, new object[] { value });
}

This will throw an exception:

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow;      // works as expected
SetProperty(propertyBag, "Value", 42);  // throws a NotImplementedException

I used properties in this example because they are easier to implement but obviously the same applies to methods too. The reason for this is that dynamic is dynamically evaluated at runtime but reflection can only reflect on the static implementation. (What properties should GetProperties return on the PropertyBag class?)

If you are using dynamic with ordinary C# objects reflection will work as expected but you cannot rely on that if you don't know what type of runtime binder you are adressing and how it is implemented internally.

pescolino
  • 3,086
  • 2
  • 14
  • 24
1

By reflection I think you can do something like that (if it's private ->NonPublic)

MethodInfo dynMethod = this.GetType().GetMethod("MethodName" + itemType, BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(this, new object[] { methodParams });

Simply use the overloaded version of GetMethod that accepts BindingFlags:

1

Short answer, yes, you can do something like this:

        class MyClass { public void Action() { Console.WriteLine("Do action"); } }
        // ...
        dynamic instance = new MyClass();
        instance.GetType().GetMethod("Action").Invoke(instance, null);

However in this case, the fact that the instance is a dynamic type does absolutely nothing. You can use an object type and it will work the same way. The first method in the chain, GetType() returns the typeof(MyClass) and then it's plain old fasion reflection from there on out.

Using the dynamic keyword you can do this, which is far more interesting, albeit slightly less flexible at runtime:

        dynamic instance = new MyClass();
        instance.Action();

This will lookup the action at runtime using reflection. It isn't so obvious in this example that dynamic works differently from var because the MyClass is set here, but you could use the second line to execute ANY method named action so long as the instance had a method with that name.

Paul
  • 6,188
  • 1
  • 41
  • 63
0

Yes it is possible. What you want to do is called "reflection" and is available in most higher level languages

Here is an example of reflection in C. It is actually very powerful and allows you to make your code "aware of itself" up to a certain degree

Eric
  • 19,525
  • 19
  • 84
  • 147