【问题标题】:Intercepting method invocation to c# objects拦截对 c# 对象的方法调用
【发布时间】:2015-11-09 23:03:13
【问题描述】:

我有一个混合 c# 对象,带有一些实例属性和方法,我将它传递给 IronPython。我想要的是从 Py 代码同步调度到 c# 成员,包括静态和动态。

我在 c# 对象上实现了 IDynamicMetaObjectProvider,我注意到当 Py 调用我的对象的静态方法时,以及在编译时与动态定义的实例方法时,从未使用过 BindInvokeMember 方法,但它总是被调用方法 BindGetMember。

我有点迷茫,大概这件事做不来吧?

【问题讨论】:

  • 使用 BindGetMember 是否有效? IronPython 不使用 BindInvokeMember,因为它与 Python 的语义不匹配。
  • 问题是使用 BindGetMember 我没有收到 Py 代码中用于调用方法的参数列表,所以我不知道如何调用 c# 方法。

标签: c# ironpython dynamic-language-runtime


【解决方案1】:

IronPython 将始终使用BindGetMember,然后调用结果,因为这就是 Python 的工作方式——从对象中获取属性,然后调用它。您的BindGetMember 实现应该返回另一个实现BindInvokeMember 的动态对象,该对象将包含您需要的参数。

【讨论】:

    【解决方案2】:

    我也被这个问题困住了一段时间。 解决方案是实现 BindGetMember 并返回一个元对象,其表达式指向一个函数。此函数必须返回一个委托,然后使用参数调用该委托。所以根本不使用 BindInvokeMember。这对我有用。我的代码如下所示:

             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;
        }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 2010-12-09
    相关资源
    最近更新 更多