Method-missing difficulties in C# 4.0: dynamic vs RealProxy

感情迁移 提交于 2019-12-05 06:57:57

I'll start with the long answer. Every bind of a dynamic operation in C# does approximately these three things in this order:

  1. Ask the object to bind itself if it implements IDynamicMetaObjectProvider or is a COM object, and if that fails, then...
  2. Bind the operation to an operation on a plain-old-clr-object using reflection, and if that fails, then...
  3. Return a DynamicMetaObject that represents a total failure to bind.

You're seeing the GetType calls because in step 2, the C# runtime binder is reflecting over you to try to figure out if you have a "World" method that is appropriate to call, and this is happening because the IDynamicMetaObjectProvider implementation of hello, if there is one, couldn't come up with anything special to do.

Unfortunately for you, by the time the RuntimeBinderException is thrown, we are no longer binding. The exception comes out of the execution phase of the dynamic operation, in response to the meta object returned due to step 3. The only opportunity for you to catch it is at the actual call site.

So that strategy isn't going to work out for you if you want to implement method_missing in C#. You do have some options though.

One easy option is to implement IDynamicMetaObjectProvider in your MethodMissingInterceptor, and defer to the IDMOP implementation of the wrapped object. In case of failure on the part of the inner IDMOP, you can bind to whatever you want (perhaps a call to a method_missing delegate stored in the interceptor). The downside here is that this only works for objects that are known to be dynamic objects, e.g. those that implement IDMOP to begin with. This is because you are basically inserting yourself between steps 1 and 2.

Another alternative I can think of is to implement IDynamicMetaObjectProvider, and in it, respond positively to every bind, returning a call to a method that (a) produces the same code the C# compiler would have produced to bind in the first place, and (b) catches RuntimeBinderException to call a method_missing method. The downside here is that it would be quite complicated--you'd need to generate arbitrary delegate types and the IL that uses them, against the public types in the C# runtime binder assembly which, frankly, are not meant for public consumption. But at least you'd get method missing against all operations.

I am sure there are other strategies I have not thought of, such as you seem to be hinting at about using remoting proxies. I can't imagine what they look like though and I can't say if they'd be successful.

The crux of the problem here is that C# 4.0 does not have a design that anticipates your desire to do this. Specifically, you cannot easily insert yourself between steps 2 and 3. That brings me to the short answer, which is sorry, C# 4.0 does not have method_missing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!