C# 动态语言运行时DLR方法 C# DLR是如何与Python和Ruby交互的

6次阅读

dlr是.net framework 4.0引入的动态语言运行时基础设施,为dynamic类型、表达式树编译和动态绑定提供底层支持;它不是语言,而是ironpython/ironruby等语言实现所依赖的引擎。

C# 动态语言运行时DLR方法 C# DLR是如何与Python和Ruby交互的

DLR 是什么,它不等于 IronPython 或 IronRuby

DLR(Dynamic Language Runtime)是 .NET Framework 4.0 引入的一套运行时服务,不是独立语言,而是为 dynamic 类型、表达式树编译、动态绑定提供底层支持的基础设施。它本身不“运行 Python”或“运行 Ruby”,真正做这件事的是基于 DLR 构建的语言实现——比如 IronPythonIronRuby

换句话说:DLR 是引擎,IronPython/IronRuby 是装上这个引擎的车。你不能直接用 DLR 解析 .py 文件,但可以用 ScriptEngine(来自 IronPython)加载并执行 Python 代码。

在 C# 中调用 Python 脚本:依赖 IronPython 的 ScriptEngine

要让 C# 与 Python 交互,必须引用 IronPython.dllmicrosoft.Scripting.dll(二者都属于 DLR 生态)。核心入口是 Python.CreateEngine()

var engine = Python.CreateEngine(); var scope = engine.CreateScope(); engine.Execute("print('Hello from Python')", scope);

常见问题包括:

立即学习Python免费学习笔记(深入)”;

  • 找不到 Python 类型?确认已安装 IronPython NuGet 包(注意:.NET Core/.NET 5+ 需用 IronPython.StdLib 分离包,且部分标准库功能受限)
  • 执行含中文路径或字符串时报编码错误?显式设置 engine.SetSearchPaths 并避免使用默认控制台编码
  • 想从 Python 访问 C# 对象?需用 scope.SetVariable("obj", myCSharpObj),且该对象成员需为 public,或标记 [DynamicMemberAccess]

dynamic 与 DLR 绑定的关系:不是所有 dynamic 都走 DLR

C# 的 dynamic 变量在编译期跳过静态检查,但实际分发逻辑取决于运行时对象类型:

  • 若对象是 ExpandoObject 或实现了 IDynamicMetaObjectProvider(如 IronPython 的 PythonOps 返回的对象),则走 DLR 的 MetaObject 协议,支持属性/方法动态解析
  • 若只是普通对象转成 dynamic(如 (dynamic)new object()),则仍走 CLR 的反射路径,性能更低,且不享受 DLR 缓存优化
  • DLR 会缓存绑定结果(如方法签名、属性位置),但一旦 Python 脚本修改了类结构(如 monkey patch),缓存可能失效,触发重新绑定

Ruby 交互同理,但生态支持已基本停滞

IronRuby 曾提供类似的 Ruby.CreateEngine(),但自 2011 年后官方停止维护,.NET Core 完全不兼容。目前没有活跃的、支持现代 .NET 的 Ruby 运行时构建在 DLR 上。如果你看到“C# 调用 Ruby”,大概率是通过进程启动 ruby.exe 或使用 REST API 封装,而非真正的 DLR 集成。

DLR 本身仍在 .NET 运行时中存在(例如支撑 ExpandoObjectSystem.Text.json 的动态反序列化),但它对第三方动态语言的支持,实际取决于对应语言实现是否持续跟进——而这一点,Python(IronPython)尚可维持基础功能,Ruby 则早已掉队。

text=ZqhQzanResources