我有一个混合 c# 对象,带有一些实例属性和方法,我将它传递给 IronPython。我想要的是从 Py 代码同步调度到 c# 成员,包括静态和动态。
我在 c# 对象上实现了 IDynamicMetaObjectProvider,我注意到当 Py 调用我的对象的静态方法时,以及在编译时与动态定义的实例方法时,从未使用过 BindInvokeMember 方法,但它始终被称为 BindGetMember 方法.
我有点迷茫,大概这件事做不到吧?
我有一个混合 c# 对象,带有一些实例属性和方法,我将它传递给 IronPython。我想要的是从 Py 代码同步调度到 c# 成员,包括静态和动态。
我在 c# 对象上实现了 IDynamicMetaObjectProvider,我注意到当 Py 调用我的对象的静态方法时,以及在编译时与动态定义的实例方法时,从未使用过 BindInvokeMember 方法,但它始终被称为 BindGetMember 方法.
我有点迷茫,大概这件事做不到吧?
IronPython 将始终使用BindGetMember
然后调用结果,因为这就是 Python 的工作方式——从对象中获取属性,然后调用它。您的实现应该返回另一个具有您需要的参数的BindGetMember
动态对象 implements 。BindInvokeMember
我也被这个卡住了一段时间。解决方案是实现 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;
}