Question

I have an hybrid c# object, with some instance properties and methods, and I pass it to IronPython. What I want is to syncronize the dispatch to the c# members, both static and dynamics, from Py code.

I implemented the IDynamicMetaObjectProvider on the c# object, and I noticed that when Py invokes the static methods of my object, and with instance methods, defined at compile time vs dynamics, the method BindInvokeMember is never used, but it is always called the method BindGetMember.

I'm a little confused, probably this thing can't be done?

Was it helpful?

Solution

IronPython will always use BindGetMember and then Invoke the result because that's how Python works - get the attribute from the object, then call it. Your BindGetMember implementation should return another dynamic object that implements BindInvokeMember, which will have the arguments you need.

OTHER TIPS

I also got stuck with this for a while. The solution is to implement the BindGetMember and return an meta object whichs expression Points to a function. This Function has to return a delegate which is then called with the Parameters. So BindInvokeMember is not used at all. That worked for me. My code looks like this:

         public override DynamicMetaObject BindGetMember(GetMemberBinder aBinder)
    {
        var aMetaObject = this;
        var aIsMethod = aMetaObject.IsMethod(aBinder.Name, aBinder.IgnoreCase);
        if (aIsMethod)
        {
            var aRestrictions = BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType);
            var aThisExpression = Expression.Convert(this.Expression, this.LimitType);
            var aMethodInfo = typeof(CDynamicObjectScriptAdapter).GetMethod(CDynamicObjectScriptAdapter.GetDelegate_MethodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            var aParameters = new Expression[] { Expression.Constant(aBinder) };
            var aCallExpression = Expression.Call(aThisExpression, aMethodInfo, aParameters);
            var aResult = new DynamicMetaObject(aCallExpression, aRestrictions);
            return aResult;
        }
        else
        {
            var aRestrictions = BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType);
            var aThisExpression = Expression.Convert(this.Expression, this.LimitType);
            var aMethodInfo = typeof(CDynamicObjectScriptAdapter).GetMethod(CDynamicObjectScriptAdapter.GetValue_MethodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            var aParameters = new Expression[] { Expression.Constant(aBinder) };
            var aCallExpression = Expression.Call(aThisExpression, aMethodInfo, aParameters);
            var aResult = new DynamicMetaObject(aCallExpression, aRestrictions);
            return aResult;
        }
    }

    internal const string GetDelegate_MethodName = "GetDelegate";
    internal object GetDelegate(GetMemberBinder aBinder)
    {
        var aScriptAdapter = this;
        var aAdaptedObject = aScriptAdapter.AdaptedObject;
        var aClassInfo = aAdaptedObject.ClassInfo;
        var aIgnoreCase = aBinder.IgnoreCase;
        var aCaseSensitive = !aIgnoreCase;
        var aMethodInfoDic = aClassInfo.GetScriptMethodInfoDic(aCaseSensitive);
        var aName = aBinder.Name;
        var aScriptMethodInfo = aMethodInfoDic[aName];
        var aMethodInfo = aScriptMethodInfo.MethodInfo;
        var aDelegateType = aScriptMethodInfo.ScriptMethodAttribute.DelegateType;
        var aDelegate = aMethodInfo.CreateDelegate(aDelegateType, aAdaptedObject);
        return aDelegate;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top