gpt4 book ai didi

c# - IronPython 可以向 C# 类动态添加方法吗?

转载 作者:行者123 更新时间:2023-11-30 17:04:50 25 4
gpt4 key购买 nike

我有一些在嵌入式 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 添加一些功能,但我无法修改它的代码。此外,我宁愿不从它派生也不使用扩展方法,而是使用委托(delegate)。理想情况下,我想写一些类似的东西

scope.AddMemberFunction( scope.foo, "Fun",
new Func<Foo,int>( f => return f.a + f.b ) );

然后直接在Python脚本中使用:

print( foo.Fun() )

我认为这正是使用 Operations 可以完成的事情,但这引发了一个异常,说 'Foo' 对象没有属性 'Fun'

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

最佳答案

简短回答:不,您不能修改 .NET 类。默认情况下,他们没有添加成员所需的动态 Hook 。

最好的办法是包装类并添加所需的成员; Python 使这变得简单:

class FooWrapper(object):
def __init__(self, foo):
self.foo = foo

def __getattr__(self, name):
return getattr(self.foo, name)

def mymethod(self):
...

__getattr__特殊方法仅针对不属于正常属性查找的属性调用,因此 mymethod() 将正常查找,但其他任何内容都将转发到底层对象。

如果您需要在 C# 端执行此操作,您可以通过子类化 DynamicObject 来实现相同的目的并重载 Try*Member 函数。

关于c# - IronPython 可以向 C# 类动态添加方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17043839/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com