向.NET应用程序添加脚本功能

时间:2020-03-05 18:37:19  来源:igfitidea点击:

我有一个用C#编写的小游戏。它使用数据库作为后端。它是
交易纸牌游戏,我想将纸牌的功能实现为脚本。

我的意思是,我实际上有一个接口" ICard",卡类实现该接口("公共类Card056:ICard"),并且包含游戏调用的功能。

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

那可能吗?从源文件注册一个类,然后实例化它,依此类推。

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

如果可以使用任何.NET语言编写脚本,则该语言是Cbut额外的好处。

解决方案:

是的,我曾考虑过这一点,但很快就发现另一种特定于域的语言(DSL)可能会有点过多。

本质上,他们需要以可能无法预测的方式与我的游戏状态互动。例如,一张牌可以有一条规则:"当这张牌进入游戏时,所有亡灵小兵都会对飞行中的敌人获得+3攻击,除非敌人受到祝福。"由于交易纸牌游戏是基于回合制的,因此GameState Manager将触发OnStageX事件,并允许这些纸牌以其需要的任何方式修改其他纸牌或者GameState。

如果尝试创建DSL,则必须实现相当大的功能集并可能不断对其进行更新,这将维护工作转移到了另一部分,而没有实际删除它。

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

Oleg Shilo的CScript## 解决方案(位于The Code Project)确实是在应用程序中提供脚本功能的很好的介绍。

另一种方法是考虑专门为脚本编写的语言,例如IronRuby,IronPython或者Lua。

IronPython和IronRuby现已上市。

有关嵌入IronPython的指南,请阅读

如何通过10个简单的步骤将IronPython脚本支持嵌入到我们现有的应用程序中。

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

如果我们想了解有关在.NET中构建编译器的信息,那么该代码库是一本不错的书。

换一个角度来看,尝试使用PowerShell。有许多将PowerShell嵌入到应用程序中的示例-这是一个有关该主题的详尽项目:
Powershell隧道

我们可能可以使用IronRuby。

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

如果我们真的想在运行时进行编译,则可以使用CodeDOM,然后可以使用反射来加载动态程序集。 MSDN文章可能会有所帮助。

我们可以使用任何DLR语言,它们提供了一种真正轻松地托管自己的脚本平台的方法。但是,我们不必为此使用脚本语言。我们可以使用Cand与Ccode提供程序进行编译。只要将其加载到自己的AppDomain中,就可以将其加载和卸载到心脏内容中。

如果我们不想使用DLR,则可以使用Boo(具有解释器),也可以考虑使用CodePlex上的Script.NET(S#)项目。使用Boo## 解决方案,我们可以在已编译的脚本之间进行选择,也可以使用解释器进行选择,Boo通过其开放的编译器体系结构提供了一种不错的脚本语言,灵活的语法和可扩展的语言。但是,Script.NET看起来也很不错,我们可以轻松地扩展该语言及其开放源代码项目,并使用非常友好的Compiler Generator(Irony.net)。

我的部门销售的主要应用程序执行的功能与提供客户定制非常相似(这意味着我无法发布任何来源)。我们有一个加载动态VB.NET脚本的C应用程序(尽管可以很容易地支持任何.NET语言,因为自定义团队来自ASP的背景,所以选择了VB。)

使用.NET的CodeDom,我们使用VBCodeDomProvider(令人讨厌的是,它默认为.NET 2,从数据库中编译脚本。如果要支持3.5功能,则需要通过" CompilerVersion" =" v3.5"传递字典。到其构造函数)。使用CodeDomProvider.CompileAssemblyFromSource方法进行编译(我们可以传递设置以强制其仅在内存中进行编译。

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

我建议使用LuaInterface,因为它已经完全实现了Lua,而Nua似乎并不完整,并且可能未实现某些非常有用的功能(协程等)。

如果我们要使用一些外部预包装的Lua模块,则建议使用与1.5.x相似的东西,而不是2.x系列,后者构建完全托管的代码并且不能公开必要的C API。

段落数量不匹配