2016-09-13 3 views
4

Я пытаюсь интегрировать скрипты C# в мое приложение базы данных. Я использую объект globals, чтобы сделать глобальные переменные доступными из сценария.Roslyn/CSharpScript - Как сохранить/загрузить компиляцию, чтобы избежать времени ожидания компиляции

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

Script<object> script = CSharpScript.Create(scriptCode, globalsType: typeof(MyGlobals)); 
script.Compile(); //<-- load the Compilation from database/file here 
script.RunAsync(myGlobalsInstance).Wait(); 
+0

Возможно, вы должны скомпилировать обычную сборку вместо сценария. – SLaks

+0

информация о том, как создать компиляцию вручную, - это [здесь] (http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp.Scripting/CSharpScriptCompiler.cs,49) – m0sa

ответ

-1

Если вы хотите предварительно скомпилировать, вы можете использовать классы из System.CodeDom.Compiler;

CompilerParameters opts = new CompilerParameters(); 

opts.OutputAssembly = <Destination FileName>; 
opts.ReferencedAssemblies.AddRange(<needed references>); 
//set other options;    

var codeProvider = new Microsoft.CSharp.CSharpCodeProvider(); 
var results = codeProvider.CompileAssemblyFromFile(opts, <Your script source files>); 
//check that there's no errors in the results.Errors 

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

var mydll = AppDomain.CurrentDomain.Load(<compiled Assembly From the previous step>); 
    var classInstance = <YouTypeOrInterface>mydll.CreateInstance(
     <TypeFromTheAssembly>, 
     false, 
     BindingFlags.CreateInstance, 
     null,                 
     new object[] { <Arguments you need to provides to your class constructor> },                    CultureInfo.InvariantCulture, null); 

Теперь вы можете делать то, что хотите, с этим экземпляром. Например. classInstance.ExecuteSomething (...)

+1

Обратите внимание, что сценарий C# отличается от обычного C#, поэтому попытка скомпилировать скрипты с помощью CodeDOM, вероятно, не сработает и потребует изменения скриптов. Кроме того, если вы это делаете, я не вижу причин использовать CodeDOM вместо Roslyn, который также может собирать сборки. – svick

1

Вы можете создать CSharpScript, а затем получить компиляцию через GetCompilation, чтобы получить компиляцию.

var script = CSharpScript.Create("script.."); 
var compilation = script.GetCompilation(); 

Из компиляции, вы можете на самом деле compilation.Emit() DLL, и PDB на диске или в памяти. Трудный (и внутренний бит roslyn) - это то, как заставить делегата кода выполнить, как только у вас есть сборка. Вы можете видеть, как это делает roslyn here.

+0

Итак, я могу испустить сборку для потока. Но если я правильно понимаю, нет (простого) способа загрузить данные компиляции обратно в CSharpScript? – Bogomil

+1

Зачем вам нужен CSharpScript, если у вас есть сборка (DLL)? Вы загружаете это (Assembly.Load), создаете тип (Activator.CreateType) и создаете делегат для выполнения. – m0sa

+0

AFAIK a C# script не имеет точки входа, и в моем случае он должен иметь прямой доступ к членам переменной «globals». То есть, что я хочу перегрузить из потока, и я понятия не имею, как это сделать. – Bogomil

 Смежные вопросы

  • Нет связанных вопросов^_^