Добавление функциональности сценариев в приложения .NET

У меня есть небольшая игра, написанная на C#. Он использует базу данных как серверную часть. Это карточная игра , и я хотел реализовать функцию карточек в виде скрипта.

Я имею в виду, что у меня, по сути, есть интерфейс, ICard который реализует класс карты ( public class Card056: ICard ) и который содержит функцию, вызываемую игрой.

Теперь, чтобы сделать эту вещь поддерживаемой / изменяемой, я хотел бы иметь класс для каждой карты в качестве исходного кода в базе данных и по существу компилировать его при первом использовании. Поэтому, когда мне нужно добавить / изменить карту, я просто добавлю ее в базу данных и скажу своему приложению обновить, без необходимости развертывания сборки (тем более, что мы говорим о 1 сборке на карту, что означает сотни сборок) .

Это возможно? Зарегистрируйте класс из исходного файла, а затем создайте его экземпляр и т. Д.

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

Язык - C#, но дополнительный бонус, если можно написать сценарий на любом языке .NET.

Ответов (9)

Решение

Решение C# Script от Олега Шило (в The Code Project ) действительно является отличным введением в обеспечение возможностей сценариев в вашем приложении.

Другой подход - рассмотреть язык, специально созданный для написания сценариев, например IronRuby , IronPython или Lua .

IronPython и IronRuby доступны уже сегодня.

Чтобы получить руководство по внедрению IronPython, прочитайте статью « Как встроить поддержку скрипта IronPython в ваше существующее приложение за 10 простых шагов» .

Lua - это язык сценариев, обычно используемый в играх. Существует компилятор Lua для .NET, доступный на CodePlex - http://www.codeplex.com/Nua

Эта кодовая база - отличное чтение, если вы хотите узнать о создании компилятора в .NET.

Совсем другое дело - попробовать PowerShell . Существует множество примеров встраивания PowerShell в приложение - вот подробный проект по этой теме: Powershell Tunnel

Я использую LuaInterface1.3 + Lua 5.0 для приложения NET 1.1.

Проблема с Boo заключается в том, что каждый раз, когда вы анализируете / компилируете / оцениваете свой код на лету, он создает набор классов boo, поэтому вы получаете утечки памяти.

Lua, с другой стороны, этого не делает, поэтому он очень стабилен и отлично работает (я могу передавать объекты из C# в Lua и обратно).

Пока я еще не поместил его в PROD, но кажется очень многообещающим.

У меня были проблемы с утечкой памяти в PROD с использованием LuaInterface + Lua 5.0 , поэтому я использовал Lua 5.2 и напрямую связался с C# с помощью DllImport. Утечки памяти были внутри библиотеки LuaInterface.

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

Как только я это сделал, все утечки памяти исчезли, и приложение стало очень стабильным.

Вы можете использовать любой из языков DLR, что дает возможность действительно легко разместить вашу собственную платформу сценариев. Однако для этого необязательно использовать язык сценариев. Вы можете использовать C# и скомпилировать его с помощью поставщика кода C#. Пока вы загружаете его в отдельный домен приложений, вы можете загружать и выгружать его, сколько душе угодно.

Да, я думал об этом, но вскоре сообразил, что другого доменно-ориентированного языка (DSL) было бы слишком много.

По сути, им нужно взаимодействовать с моим игровым состоянием, возможно, непредсказуемым образом. Например, карта может иметь правило «Когда эти карты входят в игру, все ваши миньоны-нежить получают +3 к атаке против летающих врагов, кроме тех случаев, когда враг благословлен». Поскольку коллекционные карточные игры являются пошаговыми, GameState Manager запускает события OnStageX и позволяет картам изменять другие карты или GameState в соответствии с потребностями карты.

Если я попытаюсь создать DSL, мне придется реализовать довольно большой набор функций и, возможно, постоянно обновлять его, что переносит работу по обслуживанию в другую часть, фактически не удаляя ее.

Вот почему я хотел остаться с «настоящим» языком .NET, чтобы иметь возможность просто запускать событие и позволять карте манипулировать состоянием игры любым способом (в пределах безопасности доступа кода).

Возможно, вы сможете использовать для этого IronRuby.

В противном случае я бы посоветовал вам иметь каталог, в котором вы размещаете предварительно скомпилированные сборки. Тогда у вас может быть ссылка в БД на сборку и класс и использование отражения для загрузки соответствующих сборок во время выполнения.

Если вы действительно хотите компилировать во время выполнения, вы можете использовать CodeDOM, тогда вы можете использовать отражение для загрузки динамической сборки. Статья в документации Microsoft, которая может помочь .

Если вы не хотите использовать DLR, вы можете использовать Boo (у которого есть интерпретатор) или рассмотреть проект Script.NET (S #) на CodePlex . С помощью решения Boo вы можете выбирать между скомпилированными сценариями или использованием интерпретатора, а Boo создает хороший язык сценариев, имеет гибкий синтаксис и расширяемый язык благодаря своей открытой архитектуре компилятора. Однако Script.NET выглядит неплохо, и вы можете легко расширить этот язык, а также его проект с открытым исходным кодом и использовать очень удобный генератор компилятора ( Irony.net ).

Главное приложение, которое продает мое подразделение, делает что-то очень похожее на предоставление настроек клиента (что означает, что я не могу публиковать какой-либо источник). У нас есть приложение C#, которое загружает динамические сценарии VB.NET (хотя любой язык .NET может быть легко поддержан - VB был выбран, потому что группа настройки пришла из фона ASP).

Используя .NET CodeDom, мы компилируем скрипты из базы данных, используя VB CodeDomProvider (досадно, что по умолчанию используется .NET 2, если вы хотите поддерживать функции 3.5, вам нужно передать словарь с "CompilerVersion" = "v3.5" в его конструктор. ). Используйте CodeDomProvider.CompileAssemblyFromSource метод для его компиляции (вы можете передать настройки, чтобы заставить его компилироваться только в памяти.

Это приведет к тому, что в памяти будут храниться сотни сборок, но вы можете собрать код всех динамических классов вместе в одну сборку и перекомпилировать всю партию при любых изменениях. Это имеет то преимущество, что вы можете добавить флаг для компиляции на диске с PDB, когда вы тестируете, что позволяет вам отлаживать динамический код.

Я бы предложил использовать LuaInterface, поскольку он полностью реализовал Lua, где кажется, что Nua не является полным и, вероятно, не реализует некоторые очень полезные функции (сопрограммы и т. Д.).

Если вы хотите использовать некоторые из предварительно упакованных модулей Lua, я бы предложил использовать что-то вроде 1.5.x в отличие от серии 2.x, которая создает полностью управляемый код и не может предоставить необходимый C API.

В следующей версии .NET (5.0?) Много говорилось об открытии «компилятора как службы», который сделал бы возможными такие вещи, как прямая оценка сценария.