我有一些用于嵌入式 IronPython 脚本的简单 C# 类型:
//simple type
public class Foo
{
public int a;
public int b;
}
var engine = IronPython.Hosting.Python.CreateEngine();
dynamic scope = engine.CreateScope();
scope.foo = new Foo{ a = 1, b = 2 };
engine.Execute( "print( foo.a )", scope );
我想添加一些功能,Foo
但我无法修改它的代码。此外,我宁愿不从它派生也不使用扩展方法,而是使用委托。理想情况下,我想写一些类似的东西
scope.AddMemberFunction( scope.foo, "Fun",
new Func<Foo,int>( f => return f.a + f.b ) );
然后直接在Python脚本中使用:
print( foo.Fun() )
我认为这正是使用'Foo' 对象没有属性 'Fun'Operations
可以完成的事情,但这引发了一个异常
engine.Operations.SetMember( scope.foo, "Fun",
new Func<Foo, int>( f => f.a + f.b ) );
接下来我尝试了 Python 的方式(比如 Foo 位于 IronPythonApp 的命名空间中,并且它的程序集被添加到 engine.Runtime 中):
import IronPythonApp
def Fun( self ):
return self.a + self.b
IronPythonApp.Foo.Fun = Fun
但这给出了类似的例外:无法设置内置/扩展类型“Foo”的属性
有没有办法修改 IronPython 内部生成的 Python 类定义?
更新
我探索了 Jeff Hardy 的回答中的一些选项。这里有两种方法都可以变得非常可扩展(这里只显示简单的方法)
扩展对象!
var foo = new Foo { a = 1, b = 2 };
dynamic exp = new ExpandoObject();
exp.Fun = new Func<int>( () => foo.a + foo.b );
exp.a = foo.a; //automating these is not a big deal
exp.b = foo.b; //
//now just add exp to the scope and done.
毕竟使用 SetMember
scope.origFoo = new Foo { a = 1, b = 2 };
//the only variable thing in this string is 'origFoo'
//so it's no big deal scaling this
engine.Execute( @"
class GenericWrapper( object ) :
def __init__( self, foo ):
self.foo = foo
def __getattr__( self, name ) :
return getattr( self.foo, name )
foo = GenericWrapper( origFoo )", scope );
//ha, now scope contains something that we can mess with after all
engine.Operations.SetMember( scope.foo, "Fun",
new Func<int>( () => scope.foo.a + scope.foo.b ) );
engine.Execute( "print( foo.Fun() )", scope );