I use a type derived from a DynamicObject as a builder for some strings. At the end I call ToString to get the final result.
At this point
That's because ToString called on dynamic is typed to return dynamic and not string:
dynamic example = new Example();
// test will be typed as dynamic
var test = example.ToString();
When you call ToUpper on test it will use dynamic binding and resolve to string.ToUpper at runtime. You have to cast to a concrete type to escape dynamic typing.
Extension methods is a compile-time feature and as such is not supported by dynamic typing as extension method. You can still call it using regular static method invocation syntax.
Extensions.Extension(example.ToString());
But again - example.ToString() will return dynamic and type binding will happen at runtime to check if it can be used as a parameter to Extensions.Extension call. Check this answer for details.