3

Here is my code:

public static class DynamicExtensions

    public static void Add(this ExpandoObject obj, string path){
        dynamic _obj = obj;
        if (_obj == null) throw new ArgumentNullException("obj");
        _obj.path = path;
    }
}

But I got the error of "'System.Dynamic.ExpandoObject' does not contain a definition for 'Add'", when I call it in this way:

dynamic obj = new ExpandoObject();
obj.Add("p1");

How to fix it?

Thanks in advance!

zs2020
  • 53,766
  • 29
  • 154
  • 219
  • @JaneDoe Yes, the code compiles. I think maybe it is impossible for the compiler to tell whether Add is a dynamic method or an extension method. โ€“ zs2020 Sep 19 '12 at 19:48
  • possible duplicate of [Extension method and dynamic object in c#](http://stackoverflow.com/questions/5311465/extension-method-and-dynamic-object-in-c-sharp) โ€“ nawfal Jul 19 '14 at 21:00

2 Answers2

13

The problem is using dynamic with extension methods - the two just don't go together. This would be fine:

ExpandoObject obj = new ExpandoObject();
obj.Add("p1");

... but with just dynamic, there's no extension method support.

From section 7.6.5.2 of the C# 5 spec:

In a method invocation (ยง7.5.5.1) of one of the forms

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )

if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. If expr or any of the args has compile-time type dynamic, extension methods will not apply.

While the compiler could remember the using directives which it would have to check to apply extension methods, it just doesn't - perhaps for performance reasons, or perhaps because it was just felt to be a lot of work for relatively little benefit.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
6

Dynamic explicitly excludes extension methods. This is because the method is resolved at run time, not compile time. To resolve the method call correctly, the DLR would need information about the call that includes which using directives are in force; there's no mechanism to do that. See this answer by Eric Lippert for more detail: https://stackoverflow.com/a/5313149/385844

You can, of course, call the method using the static method call syntax:

DynamicExtensions.Add(obj, "p1");
Community
  • 1
  • 1
phoog
  • 42,068
  • 6
  • 79
  • 117
  • A different way to work around the limitation which might be useful is: `((ExpandoObject)a).Add("p1")`. (It might look as if the compiler shouldn't need this 'hint' at all; but remember that, except in very trivial cases, the compiler doesn't know until run-time whether there is a method called `Add` on the dynamic object itself!) โ€“ MikeBeaton Sep 12 '16 at 17:13