2013-06-11 5 views
3

나는 임베디드 IronPython의 스크립트에 사용되는 몇 가지 간단한 C# 유형이 있습니다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)); 

처럼 뭔가를 작성하고 다음 직접 파이썬 스크립트에서 사용하고 싶습니다 :

print(foo.Fun()) 

나는 이것이 Operations 사용하여 수행 할 수 있는지 정확하게라고 생각하지만, 이것은 예외가 발생 말하는 '푸'개체가 나는 것 (푸에 말의 파이썬 방법을 시도

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

다음 어떤 속성 '재미'가 없다

import IronPythonApp 

def Fun(self): 
    return self.a + self.b 

IronPythonApp.Foo.Fun = Fun 

하지만이 비슷한 예외를 제공합니다 : '푸'

내장/확장 유형의 속성을 설정할 수이며이 어셈블리)를 engine.Runtime에 추가 될 것 네임 스페이스 IronPythonApp

내부적으로 ironPython이 생성하는 Python 클래스 정의를 수정하는 방법이 있습니까?

업데이트 제프 하디의 대답에 의해 같은 일부 옵션을 탐구. 두 가지 방법으로 두 가지 방법으로 확장 성을 높일 수 있습니다 (여기서 간단히 보여줍니다)

ExpandoObject!

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

답변

2

짧은 답변 후 : 아니, 당신은 .NET 클래스를 수정할 수 없습니다. 기본적으로 멤버를 추가하는 데 필요한 동적 후크가 없습니다.

가장 좋은 방법은 클래스를 래핑하고 원하는 멤버를 추가하는 것입니다. 파이썬이 쉽게 :

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 함수를 오버로드하여 동일한 결과를 얻을 수 있습니다.

+0

+1 두 가지 방법을 모두 시도했는데 작동합니다.하지만 제작 과정에서 일반적이고 유용하게 사용할 수있는 작업이 많이 있습니다. – stijn

관련 문제