如何将带类型信息的Python函数通过IronPython转为强类型C#函数
解决方案
C# 泛型参数属于编译时静态确定的语法元素,无法直接使用运行时从Python上下文获取的类型变量作为泛型参数,你期望的直接传入Python侧functionTypes作为泛型参数的写法无法直接实现,可通过以下两种路径实现需求:
固定类型场景实现方案
如果提前知晓Python函数的输入输出类型,直接显式指定泛型参数即可,IronPython会自动完成Python类型和C#类型的映射转换:
class Program { public static void Main(string[] args) { var engine = Python.CreateEngine(); var scope = engine.CreateScope(); var source = engine.CreateScriptSourceFromString( "def Add(arg1, arg2):\n" + " return arg1 +1\n" + "\n" + "functionTypes = int" + "\n" + "class MyClass(object):\n" + " def __init__(self, value):\n" + " self.value = value\n"); source.Execute(scope); // 显式指定Func泛型类型为int,和Python侧定义的类型对齐 var Add = scope.GetVariable<Func<int, int, int>>("Add"); Console.WriteLine(Add(2,3)); } }
任意入参函数通用解决方案
针对参数数量、类型不固定的Python函数,有两种通用实现方式:
- 动态类型调用方案
使用C#的dynamic类型接收Python函数,绕过编译时类型检查,运行时自动适配参数和返回值类型,无需提前声明函数签名:
// 无需指定泛型类型,直接获取为dynamic dynamic Add = scope.GetVariable("Add"); // 直接调用,支持任意参数数量、类型 var result = Add(2, 3); Console.WriteLine(result);
该方案实现最简单,适配所有Python函数,缺点是没有编译时类型校验,参数写错只会在运行时报错。
- 运行时动态构造委托方案
如果需要得到强类型委托实例,可通过反射根据Python侧获取的类型信息动态生成对应泛型的委托:
// 从Python侧获取类型信息 Type pyArgType = scope.GetVariable<Type>("functionTypes"); // 构造对应参数数量的Func泛型类型,示例为2个入参1个返回值 Type funcGenericType = typeof(Func<,,>).MakeGenericType(pyArgType, pyArgType, pyArgType); // 生成对应类型的委托实例 Delegate addFunc = (Delegate)scope.GetVariable("Add", funcGenericType); // 调用委托 var result = addFunc.DynamicInvoke(2, 3); Console.WriteLine(result);
该方案可以根据Python侧的类型定义动态适配,支持任意参数数量的函数,只需切换对应的Func/Action泛型定义即可。
内容的提问来源于stack exchange,提问作者user16756428
相关产品推荐
相关产品推荐

