This project is read-only.

Passing the "value" parameter of BindSetMember() to a "call" expression.

Aug 12, 2013 at 4:46 AM
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { }
Just a quick question regarding the above 'value' parameter - I have to construct a "call" expression to pass "value" to my method. It seems I can pass value.Expression as an argument, or Expression.Constant(value.Value). What is the proper way, and why? Is there a proper way?

Aug 12, 2013 at 4:04 PM
The specifics of what's proper will depend on semantics of the dynamic binding that you're implementing. What's crucial is that the BindingRestrictions you return are consistent with both those semantics and the way that you build the expression tree.

If the runtime type of the object is sufficient to determine the dynamic dispatch, then you should use value.Expression as the argument and BindingRestrictions.GetTypeRestriction to build the restriction. If each object needs to be examined individually to determine how dispatch should be performed (regardless of the type of the object), then you could use Expression.Constant(value.Value) as the argument and you must use BindingRestrictions.GetInstanceRestriction to build the restriction. Note that "baking in" the object in this way may have implications on how long it's kept alive by the GC.

The chief advantages of using the expression and a less-narrow restriction are that the call site will stay smaller and faster, and the expensive runtime compilation step will be invoked less often.
Aug 12, 2013 at 5:21 PM

Please see the docs sites-binders-dynobj-interop.doc or sites-binders-dynobj-interop.pdf -- modified 09 JUL 09 at .

Section 6.1.5 discusses briefly the differences between expression and value, checking hasvalue to ensure value is valid, etc. If hasvalue is true, yes, you could use either.


Aug 12, 2013 at 5:50 PM
I did read the manual, but much didn't make sense to me at the time, which is why I asked. :)

Aug 12, 2013 at 6:43 PM
Edited Aug 12, 2013 at 6:55 PM
Just to add: The documents don't actually do a good job of painting a good picture of what is going on in general terms easily understood. It seems like there are pieces of information scattered around the document, and somewhere in all that is the "big picture". I think the documentation needs SMALL examples, like "dynamic a = obj; a.b = 1;" and there "Here's what happens in the background...". Without examples, I'm sure many people will not "see" it the way the developers do.
Aug 12, 2013 at 8:29 PM
You might find this blog entry useful, then:

Some of Chris' other blog entries might be interesting as well.
Aug 12, 2013 at 8:36 PM
When I want to refresh my memory about how this machinery works, I do one or more of the following:

1) Make use of dynamic from C# and look at the generated code with ilspy. For example,
        public static void Test1(dynamic obj)
            obj.value = 1;
2) Implement my own minimal dynamic objects and binders and use them with a manually-defined call site. Then sprinkle breakpoints liberally and watch stuff in the debugger. For example,
    public class Binder : DynamicMetaObjectBinder {
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
            return new DynamicMetaObject(target.Expression, target.Restrictions);

    public class MyObject : IDynamicMetaObjectProvider {
        public DynamicMetaObject GetMetaObject(Expression parameter) {
            return new DynamicMetaObject(parameter, BindingRestrictions.GetTypeRestriction(parameter, typeof(MyObject)), this);

    public static class Program {
        public static CallSite<Func<CallSite, object, int, object>> SetMemberSite;

        public static void MyMain(dynamic obj) {
            if (SetMemberSite == null) {
                SetMemberSite = CallSite<Func<CallSite, object, int, object>>.Create(new Binder());

            SetMemberSite.Target(SetMemberSite, obj, 1);

        public static void MyMain() {
            var obj = new MyObject();
This approach is limited, of course, by the difficulty of debugging runtime-generated code. But you can use this technique to experiment with the
Aug 12, 2013 at 8:49 PM
Interesting, thanks. :) Call sites are a bit over my head at this point, but I'll have to look into them at some point.