IronPython function with variable number of arguments as delegate

In IronPython, I am trying to call a PythonFunction with a different number of arguments from C #. For instance,

I want to do:

def foo(a, b):
     print a, b

def bar(a, b, c = None):
     print a, b, c

p = App.DynamicEvent()
p.addHandler(foo)
p.addHandler(bar)
p.invoke("Not", "Working")

where it addHandlertakes one argument and somehow saves it in the list of methods that need to be called, and invokehas the following signature:

public virtual void invoke(params object[] tArgs)

Since I want to avoid specifics for PythonEngine(and therefore engine.Operations.Invoke()), I tried several ways to store and implement these things as delegates, but I think that the essence of my problem is that I don’t know how to save a base type MulticastDelegatecompatible with PythonFunction?

Perhaps I want to implement my own method DynamicInvoke? Any thoughts and experience will be very grateful!

, , Javascript, IronPython #. Javascript: Client.doThing("something", 4, {"key:"value"}) python :

def doThing(s, i, d):
    pass

:

doThingEvent = App.DynamicEvent()
doThingEvent.addHandler(doThing)
WebBrowser.handleMethod("doThing", doThingEvent);
+3
2

digEmAll, , System.Action -. addHandler, PythonFunction, Delegate, , :

def foo(a, b):
     print a, b

def bar(a, b, c = None):
     print a, b, c

p = DynamicEvent(engine)
p.addHandler(foo)
p.addHandler(bar)

p.invoke("a", "b")
p.invoke("a", "b", "c")

#:

public class DynamicEvent
{
    private Dictionary<int, Action<object[]>> delegates = new Dictionary<int, Action<object[]>>();
    public ScriptEngine Engine { get; set; }


    public DynamicEvent(ScriptEngine engine)
    {
        Engine = engine;
    }

    public void addHandler(PythonFunction pythonFunction)
    {
        int args = (int) pythonFunction.func_code.co_nlocals;
        delegates.Add(args, a => Engine.Operations.Invoke(pythonFunction, a));
    }

    public void addHandler(Delegate d)
    {
        int args = d.Method.GetParameters().Length;
        delegates.Add(args, a => d.DynamicInvoke(a));
    }

    public void invoke(params object[] args)
    {
        Action<object[]> action;
        if(!delegates.TryGetValue(args.Length, out action))
            throw new ArgumentException("There is no handler that takes " + args.Length + " arguments!");

        action(args);
    }
}

, engine script, .

, !


. Delegate PythonFunction :

Delegate target = pythonFunction.__code__.Target;
var result = target.DynamicInvoke(new object[] {pythonFunction, args});

, Engine.Operations.Invoke(), Delegate "" Delegate.

0

PythonFunction , , Action<...>

. Python, - :

import sys
import clr
import System
from System import *

def foo(a, b):
     print a, b

def bar(a, b, c = "N.A."):
     print a, b, c

p = App.DynamicEvent()
p.AddHandler( Action[object,object](foo) )
p.AddHandler( Action[object,object,object](bar) )
p.DynamicInvoke("Not", "Working")

, p MulticastDelegate. , :

  • Python 16 ( Action 16 )

, , "-", - :

//
// WARNING: very very rough code here !!
//
public class DynamicEvent
{
    List<Delegate> delegates;

    public DynamicEvent()
    {
        delegates = new List<Delegate>();
    }
    public void AddHandler(Delegate dlgt)
    {
        delegates.Add(dlgt);
    }
    public void Invoke(params object[] args)
    {
        foreach (var del in delegates)
        {
            var parameters = del.Method.GetParameters();
            // check parameters number
            if (args.Length != parameters.Length)
                continue; // go to next param

            // check parameters assignability
            bool assignable = true;
            for (int i = 0; i < args.Length; i++)
            {
                if (!parameters[i].ParameterType.IsInstanceOfType(args[i]))
                {
                    assignable = false;
                    break; // stop looping on parameters
                }
            }
            if (!assignable)
                continue; // go to next param

            // OK it seems compatible, let invoke
            del.DynamicInvoke(args);
        }
    }
}

N.B:.

, , , , .

, , , args ... , IronPython:)

+3

Source: https://habr.com/ru/post/1767665/


All Articles