我试图执行以下操作:
这是一个展示我想要做的事情的例子。实际上,IWoof
接口上有更多方法。
C#类和接口:
namespace Foo
{
public interface IWoof { string DoSomething(); }
public class Bar
{
public Bar() { Woof = new WoofImp(); }
public IWoof Woof { get; set; }
}
public class WoofImp : IWoof
{
public string DoSomething()
{
return "DoSomething executing in C#";
}
}
}
我想使用bar.Woof
并将其替换为IronPython代理。我想从IronPython脚本中做到这一点。我尝试过各种各样的事情。
我定义了一个像这样的包装器:
class Wrapper(object):
def __init__(self, obj):
self._obj = obj
def __getattr__(self, name):
print '__getattr__ called'
if name == "DoSomething":
return self.__DoSomething
else:
return object.__getattr__(self, name)
def __DoSomething(self):
result = self._obj.DoSomething()
return result + " AND DoSomething executing in Python"
这正常,正如您所期望的那样:
import Foo
bar = Foo.Bar()
woof = Wrapper(bar.Woof)
print woof.DoSomething()
> DoSomething executing in C# AND DoSomething executing in Python
但是,当我尝试用包装对象替换bar.Woof时,它不起作用:
bar.Woof = woof_wrapper
> TypeError: expected IWoof, got Object_1$1
> Microsoft.Scripting.ArgumentTypeException: expected IWoof, got Object_1$1
at CallSite.Target(Closure , CallSite , Object , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
显然我的包装器需要实现IWoof
接口,所以我试过了。
class Wrapper_IWoof(object, Foo.IWoof): # Inherits from IWoof
... etc
现在我可以添加包装器实例并尝试像这样调用它:
woof = Wrapper_IWoof(bar.Woof)
bar.Woof = woof
print bar.Woof.DoSomething()
但是我遇到了一个新问题:
> AttributeError: 'Wrapper_IWoof' object has no attribute 'DoSomething'
> System.MissingMemberException: 'Wrapper_IWoof' object has no attribute 'DoSomething'
at IronPython.Runtime.Operations.PythonOps.MissingInvokeMethodException(Object o, String name)
at IronPython.NewTypes.System.Object#IWoof_4$4.DoSomething()
at Microsoft.Scripting.Interpreter.FuncCallInstruction`2.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.LightLambda.Run3[T0,T1,T2,TRet](T0 arg0, T1 arg1, T2 arg2)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
我也尝试过这里描述的这种方法(并再次实现IWoof): http://www.ronnie-midnight-oil.net/2008/11/checking-type-contract-from-ironpython.html 但是,它们导致了上述两次尝试中发现的相同问题。
解决同一问题的另一种方法是通过反射生成一个python类并使用它。我做到了这一点并且有效。这给了我明确的函数声明,如下面Jeff Hardy所描述的那样。
但是,我真的很想知道上述尝试为什么不起作用。我做错了什么或遗失了什么?
答案 0 :(得分:0)
我认为你使用__getattr__
使事情过于复杂。尝试直接实现界面:
class Wrapper_IWoof(object, Foo.IWoof):
def __init__(self, obj):
self._obj = obj
def DoSomething(self):
result = self._obj.DoSomething()
return result + " AND DoSomething executing in Python"