ObjectOperations for calling BindDeleteMember

May 23, 2010 at 1:20 AM

In C#, I know I can use a Python engine's ObjectOperations to delete a member from an instance of a Python class. Now, if instead of a Python class, I have a class that looks like the following:

class MyMetaObject : DynamicMetaObject
{
    public override DynamicMetaObject BindDeleteMember(...)
    {
         ....
    }
}

I can still create a Python engine and use its ObjectOperations to delete a member of a MyMetaObject instance. However, that solution does not look right since MyMetaObject has nothing to do with Python. Any suggestion? Thanks!

May 23, 2010 at 1:37 AM

You could implement your own code that was the equivalent of what's in ObjectOperations. If I were going to do this, I would probably start with the implementation of DynamicObjectHelpers.GetMember that's in the Sympl source code, and modify it to do a DeleteMember instead.

May 23, 2010 at 6:03 AM

Thank you so much for the pointer. Do you know how to use ObjectOperations to do 'get/set/delete index'? ObjectOperations has methods for removing members, creating instances, etc. But I can't find methods for 'get/set/delete index'. 

May 23, 2010 at 1:39 PM

Yeah, I don't think it has them. If you're using C# 4.0, you can just use its GetIndex/SetIndex functionality:

dynamic obj = GetMyDynamicObject();
dynamic objsub4 = obj[4]; // Uses a GetIndex call site
obj[0] = "Hello world"; // Uses a SetIndex call site

For DeleteIndex, you'd have to roll your own -- as C# does not support this operation. The good news is that any of these binders is generally pretty easy to write if you know that the object it needs to handle is an IDynamicMetaObjectProvider. That's because the IDMOP's MetaObject should really be doing all the hard work. All you need to do is generate some kind of fallback code -- usually an error -- and figure out the right caching strategy for the call site. Here's a simple "DeleteIndex" implementation that works with a single integer index. It's easily changed to handle non-integer or multiple indexes. Caching is probably a little more troublesome, and is going to depend on your expected patterns of usage.

    public static void DeleteIndex(IDynamicMetaObjectProvider o, int index) {
        var site = CallSite<Action<CallSite, object, int>>.Create(new MyDeleteIndexBinder(1));
        site.Target(site, o, index);
    }

    class MyDeleteIndexBinder : DeleteIndexBinder {
        internal MyDeleteIndexBinder(int indexCount = 1) : base(new CallInfo(indexCount)) { }

        public override DynamicMetaObject FallbackDeleteIndex(
                DynamicMetaObject target,
                DynamicMetaObject[] indexes,
                DynamicMetaObject errorExpression) {
            // TODO: Might need better restrictions
            return errorExpression ?? new DynamicMetaObject(
                Expression.Throw(Expression.New(typeof(IndexOutOfRangeException)), typeof(object)),
                BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType)
                );
        }
    }
Coordinator
May 24, 2010 at 4:27 PM

While Curt has given a great answer (with code :-)), I thought I'd throw something on our design rationale in case it was interesting to folks. We wrestled back and forth on having a notion of a default ObjOps or default ScriptEngine. The casual intuition is "hey, I want to do X, why isn't there some default static helpers that do that?" As you said, it feels weird you're talking to Python just to talk to a DynObj :-).

We finally concluded there is no meaningful default static helpers. There might be a set of them, but then there's a slippery slope to some highly complicated parameterized helpers that you'd have to know so much to use that you may as well have written your own static helpers :-). The problem comes down to the assumptions people make and even doing something simple like invoking a callable object. How should parameters be processed? The default could be as simple as Sympl's binders, but then ref params do not work, no implicit conversions work (even "obvious" ones like unsigned-byte-8 to int), rest args do not work, etc. Then you might say, well, do some of the "obvious" stuff and have more binding logic. Turns out some folks think "obvious" means what C# does, some think it is what IronPython does, but pretty quickly you find people start disagreeing on the "obvious" behaviors and move into the parameterized solution. The next thing is the "default language" really starts to look like a set of design decisions and linguistic trade-offs that smack of real language design and semantics :-). We finally felt the "free market" might generate and tell us what most people liked as the "obvious defaults".

We may come back to this at some point, or say, encourage C# to ship a set of default helpers, but then it is clear what those defaults will do :-).

Cheers,

Bill

From: rovers [mailto:notifications@codeplex.com]
Sent: Saturday, May 22, 2010 6:21 PM
To: Bill Chiles
Subject: ObjectOperations for calling BindDeleteMember [dlr:213539]

From: rovers

In C#, I know I can use a Python engine's ObjectOperations to delete a member from an instance of a Python class. Now, if instead of a Python class, I have a class that looks like the following:

class MyMetaObject : DynamicMetaObject
{
    public override DynamicMetaObject BindDeleteMember(...)
    {
         ....
    }
}

I can still create a Python engine and use its ObjectOperations to delete a member of a MyMetaObject instance. However, that solution does not look right since MyMetaObject has nothing to do with Python. Any suggestion? Thanks!

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com