Динамическая компиляция и внедрение полученного кода в приложение - C#
Формулировка задачи:
В приложении потребовались макросы. Мне подходит синтаксис C#, поэтому хочу использовать динамическую компиляцию. Вопрос по интеграции скомпилированного кода и взаимодействию его с остальным объектами в приложении. В примерах с динамической компиляцией обычно компилируют новый класс, затем создают экземпляр объекта этого класса и затем дергают у него методы.
Я же хочу дополнить (добавить,переопределить...) скомпилированным кодом метод в имеющимся классе, чтобы из него можно было обращаться к приватным переменным и методам. Как лучше сделать что-то подобное?
где application.exe - сама программа. Но это как-то совсем некрасиво. Как сделать правильно?
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
...
class MacrosClass
{
private int Var1 = 3;
private int Var2 = 5;
// Код макроса примерно такой
private string MacrosCode =
@"
int a = Method1();
int b = Var1 + Var2 + a;
Method2(b);
";
public void MacrosCompileAndExecute()
{
// Настраиваем компилятор
Dictionary<string, string> providerOptions = new Dictionary<string, string>
{
{"CompilerVersion", "v3.5"}
};
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
CompilerParameters compilerParams = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true
};
// Компиляция
CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, MacrosCode);
// Что делать дальше?
}
private int Method1()
{
...
}
private void Method2(int var)
{
...
}
}
Смотрел еще DynamicMethod. Примерно то, что нужно, но надо чтобы принимал код C#. MSIL для макросов слишком суров и никак не подходит.
Еще вопрос, из компилируемой динамически программы недоступны классы из основной. Namespaces указаны верно, проблема в references. Помогает такое:
CompilerParameters compilerParams = new CompilerParameters
{
...
ReferencedAssemblies = { "application.exe" }
};Решение задачи: «Динамическая компиляция и внедрение полученного кода в приложение»
textual
Листинг программы
public class Test
{
public static int Run()
{
var Provider = new Microsoft.CSharp.CSharpCodeProvider();
var Param = new System.CodeDom.Compiler.CompilerParameters();
var Code = @"
using System;
public class Class1
{
public int Method()
{
return Test.MethodA(2) + 4 * Test.MethodB(2);
}
}
";
Param.CompilerOptions = "/optimize+";
Param.GenerateInMemory = true;
Param.ReferencedAssemblies.Add( System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].Name );
var Result = Provider.CompileAssemblyFromSource( Param, new string[] { Code } );
if (Result.Errors.Count > 0)
{
MessageBox.Show( Result.Errors[0].ErrorText );
return -1;
}
dynamic Class1 = Result.CompiledAssembly.CreateInstance( "Class1" );
return Class1.Method();
}
public static int MethodA(int a)
{
return a * 2;
}
public static int MethodB(int b)
{
return b * 3;
}
}