Скриптование под .NET на JScript

от автора

Хочу показать простой пример, как просто с помощью стандартных средств подгружать яваскриптовские скрипты и работать с ними. Для простоты эксперимента пусть в скриптах будут опеределяться две функции:
Name() — возвращает имя скрипта, которое могло бы в реальной игре быть именем бота.
Do(x, y) — некая функция, которая принимает два числовых аргумента, что-то делает и возвращает результат. В реальной игре она могла бы отвечать за поведение бота.

Код скриптов.

Dummie.js

import System;  package Script {     class Dummie     {         function Name()         {             return "Dummie";         }                  function Do(x, y)         {             var rnd = new Random(DateTime.Now.Millisecond);             return rnd.Next();         }     } }

Schoolboy.js

package Script {     class Schoolboy     {         function Name()         {             return "Schoolboy";         }                  function Do(x, y)         {             return x + y;         }     } }

Genius.js

package Script {     class Genius     {         function Name()         {             return "Genius";         }                  function Do(x, y)         {             return x * y;         }     } }

Как видим, имена разные, поведение разное. Также видим, что это не совсем JavaScript, это JScript.NET, что добавляет возможность юзать из скриптов сборки фреймворка (в Dummie.js используется генератор случайных чисел из пространства имён System).

Положим скрипты в папку Scripts.

Теперь пишем код на шарпе.

const string scriptsDirectory = "Scripts"; var list = (from file in Directory.GetFiles(scriptsDirectory, "*.js")     let codeProvider = new Microsoft.JScript.JScriptCodeProvider()     let cp = new CompilerParameters     {         GenerateExecutable = false,          GenerateInMemory = true,          TreatWarningsAsErrors = true     }     select codeProvider.CompileAssemblyFromFile(cp, file) into results      select results.CompiledAssembly.GetTypes() into types     from t in types     where t.IsClass && t.Namespace == "Script"     select t into solver     select Activator.CreateInstance(solver)).ToList();

Ничего сложного нет. Выбираем все файлы из директории Scripts, которые имеют расширение ".js", компилируем каждый файл в сборку в памяти, выбираем из этих сборок классы, находящиеся в пространстве имён «Script» (в скриптах пространство имён задаётся как пакет), создаём экземпляры этих классов и ложим их в список.
Linq во всей красе. То, что на C++ потребует уйму кода, на C# делается вот так просто.

foreach (dynamic obj in list)     Console.WriteLine("{0}: {1}", obj.Name(), obj.Do(1, 2));

Выбираем из списка по очереди созданные нами на предыдущем шаге объекты и дёргаем методы Name() и Do(). Объекты динамические, чтобы не возиться с рефлекшеном. По-хорошему, тут стоит обрабатывать ситуации, когда этих методов в скриптах не окажется, но я решил не загромождать код.

Запускаем программу, получаем что-то вроде вот этого:

Dummie: 890743837 Genius: 2 Schoolboy: 3

Вот и всё. Элементарный скриптовой движок за пять минут.

ссылка на оригинал статьи http://habrahabr.ru/post/270183/