Компиляция среды выполнения C# с CSharpCodeProvider
Я имел успех, используя этот учебник: http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime чтобы установить платформу для компиляции во время выполнения и выполнения кода на C#. Ниже приведен код, который у меня есть:
public static class CodeCompiler {
public static object InterpretString(string executable) {
string compilation_string =
@"
static class RuntimeCompilationCode {
public static void Main() {}
public static object Custom() {
/* CODE HERE */
}
}";
compilation_string = compilation_string.Replace("/* CODE HERE */", executable);
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters compiler_parameters = new CompilerParameters();
// True - memory generation, false - external file generation
compiler_parameters.GenerateInMemory = true;
// True - exe file generation, false - dll file generation
compiler_parameters.GenerateExecutable = true;
// Compile
CompilerResults results = provider.CompileAssemblyFromSource(compiler_parameters, compilation_string);
// Check errors
if (results.Errors.HasErrors) {
StringBuilder builder = new StringBuilder();
foreach (CompilerError error in results.Errors) {
builder.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
}
throw new InvalidOperationException(builder.ToString());
}
// Execute
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("RuntimeCompilationCode");
MethodInfo execute = program.GetMethod("Custom");
return execute.Invoke(null, null);
}
}
Я могу передать заявление в виде строки (напр. "return 2;"
) чтобы InterpretString()
и он будет скомпилирован и выполнен как часть Custom()
функция. Однако мне интересно, возможно ли использовать тот же подход для выполнения метода, который находится в моем исходном файле. Например, предположим, CodeCompiler
у класса был другой метод returnsTwo()
который возвращает целое число 2. Есть ли способ вызвать такой метод, передав "CodeCompiler.returnsTwo();"
или аналогичная строка InterpretString()
?
1 ответ
При условии, что функция является статической функцией, это не должно быть проблемой, если вы добавите соответствующую ссылку в компиляцию. Я сделал это коротко о вещах в нескольких проектах.
Если CodeCompiler находится в вашем текущем исполняемом файле, вы должны включить ссылки следующим образом:
string exePath = Assembly.GetExecutingAssembly().Location;
string exeDir = Path.GetDirectoryName(exePath);
AssemblyName[] assemRefs = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
List<string> references = new List<string>();
foreach (AssemblyName assemblyName in assemRefs)
references.Add(assemblyName.Name + ".dll");
for (int i = 0; i < references.Count; i++)
{
string localName = Path.Combine(exeDir, references[i]);
if (File.Exists(localName))
references[i] = localName;
}
references.Add(exePath);
CompilerParameters compiler_parameters = new CompilerParameters(references.ToArray())