【问题标题】:Adding scripting functionality to .NET applications向 .NET 应用程序添加脚本功能
【发布时间】:2010-09-05 05:48:54
【问题描述】:

我有一个用 C# 编写的小游戏。它使用数据库作为后端。它是 trading card game,我想将卡片的功能实现为脚本。

我的意思是我基​​本上有一个接口ICard,它是一个卡片类实现的 (public class Card056: ICard),它包含一个由游戏调用的函数。

现在,为了使事物可维护/可修改,我希望将每张卡的类作为数据库中的源代码,并在首次使用时对其进行编译。因此,当我必须添加/更改卡片时,我只需将其添加到数据库并告诉我的应用程序刷新,而不需要任何程序集部署(特别是因为我们将讨论每张卡片 1 个程序集,这意味着数百个程序集) .

这可能吗?从源文件注册一个类,然后实例化它等等。

ICard Cards[current] = new MyGame.CardLibrary.Card056();
Cards[current].OnEnterPlay(ref currentGameState);

语言是 C#,但如果可以用任何 .NET 语言编写脚本,则额外奖励。

【问题讨论】:

  • 很有趣,我和一个朋友前段时间想用 C# 写一个集换式卡牌游戏,你不觉得你还有源吗?想知道你是如何处理这个问题的。
  • @mattytommo 不,什么都没有,它处于非常早期的阶段,基本上就像我上面概述的那样工作。现在,我会研究 Roslyn 来进行 C# 编译:blogs.msdn.com/b/csharpfaq/archive/2011/10/19/… - 或者,使用 Jint 的 JavaScript - jint.codeplex.com
  • 谢谢,但我更多的是寻找集换式卡牌游戏本身的实现和您使用的结构,而不是脚本引擎。无论如何谢谢:)

标签: c# .net scripting compiler-construction


【解决方案1】:

Oleg Shilo's C# Script solution (at The Code Project) 确实是在您的应用程序中提供脚本功能的一个很好的介绍。

另一种方法是考虑专门为脚本编写的语言,例如IronRubyIronPythonLua

IronPython 和 IronRuby 现已上市。

有关嵌入 IronPython 的指南,请阅读 How to embed IronPython script support in your existing app in 10 easy steps.

Lua 是游戏中常用的一种脚本语言。有一个适用于 .NET 的 Lua 编译器,可从 CodePlex 获得——http://www.codeplex.com/Nua

如果您想了解如何在 .NET 中构建编译器,该代码库非常适合阅读。

完全不同的角度是尝试PowerShell。有许多将 PowerShell 嵌入应用程序的示例——这里有一个关于该主题的完整项目: Powershell Tunnel

【讨论】:

  • 顺便说一句,我选择了这个作为公认的答案,因为无论如何我都想看看 Python 和 IronPython,所以 IronPython 方法最适合 。跨度>
  • LuaInterface 是一个非常棒的 lua 解释器。
  • 我在 11 月 9 日在工作流系统中实现了 C# 脚本。它对我们来说表现得非常好。
【解决方案2】:

您也许可以为此使用 IronRuby。

否则,我建议您有一个放置预编译程序集的目录。然后您可以在数据库中引用程序集和类,并使用反射在运行时加载正确的程序集。

如果你真的想在运行时编译你可以使用 CodeDOM,那么你可以使用反射来加载动态程序集。 Microsoft documentation article which might help.

【讨论】:

    【解决方案3】:

    如果您不想使用 DLR,可以use Boo (which has an interpreter) 或考虑使用the Script.NET (S#) project on CodePlex。使用 Boo 解决方案,您可以在编译脚本或使用解释器之间进行选择,Boo 是一种很好的脚本语言,具有灵活的语法和通过其开放编译器架构可扩展的语言。不过,Script.NET 看起来也不错,您可以轻松地扩展该语言及其开源项目,并使用非常友好的编译器生成器 (Irony.net)。

    【讨论】:

      【解决方案4】:

      您可以使用任何 DLR 语言,这些语言提供了一种非常轻松地托管您自己的脚本平台的方法。但是,您不必为此使用脚本语言。您可以使用 C# 并使用 C# 代码提供程序对其进行编译。只要在自己的 AppDomain 中加载它,就可以随心所欲地加载和卸载它。

      【讨论】:

        【解决方案5】:

        我建议使用LuaInterface,因为它已经完全实现了 Lua,但看起来 Nua 并不完整,并且可能没有实现一些非常有用的功能(协程等)。

        如果您想使用一些外部预打包的 Lua 模块,我建议您使用 1.5.x 中的一些东西,而不是 2.x 系列构建完全托管代码并且不能公开必要的 C API。

        【讨论】:

          【解决方案6】:

          我将 LuaInterface1.3 + Lua 5.0 用于 NET 1.1 应用程序。

          Boo 的问题在于,每次您动态解析/编译/评估代码时,它都会创建一组 boo 类,因此您会遇到内存泄漏。

          另一方面,Lua 不这样做,所以它非常稳定并且工作得很好(我可以将对象从 C# 传递到 Lua 并向后传递)。

          到目前为止,我还没有将它放入 PROD,但看起来很有希望。

          我在使用 LuaInterface + Lua 5.0 的 PROD 中确实遇到了内存泄漏问题,因此我使用了 Lua 5.2 并通过 DllImport 直接链接到 C#。 内存泄漏发生在 LuaInterface 库中。

          Lua 5.2:来自 http://luabinaries.sourceforge.nethttp://sourceforge.net/projects/luabinaries/files/5.2/Windows%20Libraries/Dynamic/lua-5.2_Win32_dll7_lib.zip/download

          一旦我这样做了,我所有的内存泄漏都消失了,应用程序非常稳定。

          【讨论】:

            【解决方案7】:

            我的部门销售的主要应用程序在提供客户定制方面非常相似(这意味着我不能发布任何来源)。我们有一个加载动态 VB.NET 脚本的 C# 应用程序(尽管可以轻松支持任何 .NET 语言 - 选择 V​​B 是因为定制团队来自 ASP 背景)。

            使用 .NET 的 CodeDom,我们从数据库编译脚本,使用 VB CodeDomProvider(令人讨厌的是,它默认为 .NET 2,如果您想支持 3.5 功能,您需要传递一个带有 "CompilerVersion" = "v3 .5" 到它的构造函数)。使用CodeDomProvider.CompileAssemblyFromSource方法编译它(你可以通过设置强制它只在内存中编译。

            这会导致内存中有数百个程序集,但是您可以将所有动态类的代码放在一个程序集中,并在发生任何更改时重新编译整个代码。这样做的好处是您可以在测试时添加一个标志以在磁盘上使用PDB 进行编译,从而允许您通过动态代码进行调试。

            【讨论】:

              【解决方案8】:

              是的,我考虑过这一点,但我很快发现另一种领域特定语言 (DSL) 会有点过分。

              基本上,他们需要以可能无法预测的方式与我的游戏状态进行交互。例如,一张牌可以有一条规则“当这张牌进场时,你所有的不死随从对飞行敌人的攻击力+3,除非敌人受到祝福”。由于集换式卡牌游戏是基于回合的,GameState 管理器将触发 OnStageX 事件并让卡牌以卡牌需要的任何方式修改其他卡牌或 GameState。

              如果我尝试创建一个 DSL,我必须实现一个相当大的功能集,并且可能会不断更新它,这会将维护工作转移到另一部分而不是实际删除它。

              这就是为什么我想继续使用“真正的”.NET 语言,以便基本上能够触发事件并让卡以任何方式(在代码访问安全性的限制内)操纵游戏状态。

              【讨论】:

              • (无需标记;虽然这应该是评论/答案更新,但在这些选项之前已被继承)
              【解决方案9】:

              .NET 的下一个版本(5.0?)有很多关于开放“编译器即服务”的讨论,这将使直接脚本评估等事情成为可能。

              【讨论】:

              • 是的。尽管 Roslyn 仍处于起步阶段,Mono.CSharp (available on NuGet) 包含所有相同的功能。
              • 添加更新以保持选项相关:.NET 编译器平台(“Roslyn”)可用。因此,它是上述所有其他方法的可行替代方案。 github.com/dotnet/roslyn.
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-11-19
              • 2015-11-21
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多