Hi, I just noticed that actually attaching the sample code might be an useful idea. :-)
-----Ursprüngliche Nachricht----- Von: Markus Schaber Hi, We have some existing C# classes using a custom event implementation which calls delegates via reflection[1]. Now, when subscribing to the event exposed by that class via IronPython, an ArgumentException is thrown: Unbehandelte Ausnahme: System.ArgumentException: MethodInfo muss ein MethodInfo-Laufzeitobjekt sein. Parametername: this bei System.Reflection.Emit.DynamicMethod.RTDynamicMethod.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) bei System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) bei EventTest.Invoke(Object[] args) in D:\playgroundSharpDevelop\IronPythonDelegateTest\Program.cs:Zeile 98. bei ScriptExecutor.Main() in D:\playgroundSharpDevelop\IronPythonDelegateTest\Program.cs:Zeile 37. Script Finished I attached a stripped down example program demonstrating this behavior. Currently, we have a workaround of using a C# wrapper method as demonstrated in the example code, but this is cumbersome, as we need to create a C# wrapper for every exposed delegate type which uses that custom event implementation internally, and we need to call that wrapper explicitly from the script. I also want to avoid to rewrite the custom event implementation, as one of our goals is to add the scripting capability in a non-intrusive way. Now is there any way I can create a working MethodInfo object from pure IronPython? Best regards Markus Schaber [1] The main reason for this custom event implementation is that this implementation internally keeps the references to the delegate target as weak references, so that subscribing to that event alone does not prevent the object from being collected. -- ___________________________ We software Automation. 3S-Smart Software Solutions GmbH Markus Schaber | Developer Memminger Str. 151 | 87439 Kempten | Germany | Tel. +49-831-54031-0 | Fax +49-831-54031-50 Email: m.scha...@3s-software.com | Web: http://www.3s-software.com CoDeSys internet forum: http://forum.3s-software.com Download CoDeSys sample projects: http://www.3s-software.com/index.shtml?sample_projects Managing Directors: Dipl.Inf. Dieter Hess, Dipl.Inf. Manfred Werner | Trade register: Kempten HRB 6186 | Tax ID No.: DE 167014915
using System; using System.Reflection; using IronPython.Hosting; using Microsoft.Scripting.Hosting; public class ScriptExecutor { private const string SRC = @" import clr def handler(sender, event): print 'Python handler: ', sender, ' with arg: ', event eventtest.Foo += handler def handler2(sender, event): print 'Wrapped python handler: ', sender, ' with arg: ', event wrapped_handler = eventtest.wrap(handler2) eventtest.Foo += wrapped_handler "; private static void Main() { try { ScriptEngine engine = Python.CreateEngine(); ScriptSource scriptSource = engine.CreateScriptSourceFromString(SRC, "test.py"); engine.Runtime.LoadAssembly(typeof(ScriptExecutor).Assembly); ScriptScope scope = engine.CreateScope(); var instance = new EventTest(); scope.SetVariable("eventtest", instance); scriptSource.Execute(scope); instance.Foo += StaticHandler; instance.Foo += new ScriptExecutor().InstanceHandler; instance.Invoke(instance, new FooEventArgs()); } finally { Console.WriteLine("Script Finished"); Console.ReadLine(); } } private static void StaticHandler(object sender, FooEventArgs e) { Console.WriteLine("Handler in C# called."); } private void InstanceHandler(object sender, FooEventArgs e) { Console.WriteLine("Instance handler in C# called."); } } public class FooEventArgs : EventArgs {} public delegate void FooEventHandler(object sender, FooEventArgs e); internal class Wrapper { internal readonly object Instance; internal readonly MethodInfo Method; internal Wrapper Next; public Wrapper(object instance, MethodInfo method, Wrapper next) { Instance = instance; Method = method; Next = next; } } public class EventTest { private Wrapper wrappers; public event FooEventHandler Foo { add { wrappers = new Wrapper(value.Target, value.Method, wrappers); } // remove left out as this is a simplified example. remove { throw new NotImplementedException(); } } public void Invoke(params object[] args) { Wrapper wrapper = wrappers; while (wrapper != null) { Console.WriteLine("Method: {0}", wrapper.Method); Console.WriteLine("Instance: {0}", wrapper.Instance ?? "<null>"); if (wrapper.Method != null) { wrapper.Method.Invoke(wrapper.Instance, args); } wrapper = wrapper.Next; } } public FooEventHandler wrap(FooEventHandler pyHandler) { return (o, e) => pyHandler(o, e); } }
_______________________________________________ Ironpython-users mailing list Ironpython-users@python.org http://mail.python.org/mailman/listinfo/ironpython-users