I am trying to pass a dynamic Ironpython object, but it looks like Ironpython is not calling TryInvokeMember. Instead, it calls TryGetMember and gives an error that cannot cause the result.
I tried this with IronPython 2.7 and 2.6.10920
ExampleCode:
DynamicObject:
class ExampleDynamicObject: DynamicObject { public override bool TryGetMember(GetMemberBinder binder, out object result) { result = "TryGetMember"; return true; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { result = "TryInvokeMember"; return true; } }
call mathode
static void Main(string[] args) { dynamic example = new ExampleDynamicObject(); var program = @"test = example.Call2(2)"; var engine = Python.CreateEngine(); var scope = engine.CreateScope(); scope.SetVariable("example", example); var source = engine.CreateScriptSourceFromString(program, SourceCodeKind.Statements); source.Execute(scope); Console.ReadKey(); }
This calls the TryGetMember method and then throws the Microsoft.Scripting.ArgumentTypeException command "str cannot be called"
This throws when the code has something like "test" (1)
So, it seems that Python does not understand that this is a function call, but simply calls a property.
But when I try to call it from C #
Console.WriteLine(example.Call); Console.WriteLine("----------------------------"); Console.WriteLine(example.Call(1));
This will work:
TryGetMember ------------------- TryInvokeMember
Does anyone have a suggestion to fix this?
Solution: (edit: namedMethodeName should be a list, otherwise nested methods will not work)
So thanks to Jeff.
When I create Dynamic as follows:
List<string> calledMethodeNames = new List<string>(); public override bool TryGetMember(GetMemberBinder binder, out object result) { calledMethodeNames.Add(binder.Name); result = this; return true; } public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) {
everything is working fine.
The hint is to return the object as a member than the object being called, and python calls TryInvoke (not TryInvokeMember)
But TryInvoke ist is called because after the return of the object, the object itself is called. So InvokeBinder does not know the name of the called method. Therefore, I store it in a variable.