Как программно откомпилировать класс и вызвать его метод?
1,00
р.
р.
Есть программа для обработки данных, и несколько раз в день меняется формула расчетов. Т.е. надо каждый раз вносить изменения в код определенного метода и компилировать сборку. Вносить изменения в код метода можно программно, просто меняя фрагмент текста. А как после замены формулы из своей программы откомпилировать код, вызвать метод и получить результат?
Ответ [c:\temp\code.cs] using System using System.Linq class Test { static public int Run(params int[] values) { return values.Sum() // эта строка часто меняется } }
Этот код компилирует code.cs, вызывает метод Test.Run и выводит результат. using System using Microsoft.CSharp using System.CodeDom.Compiler namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var code = System.IO.File.ReadAllText(@"c:\test\code.cs") var cps = new CompilerParameters() { GenerateInMemory = true, GenerateExecutable = false } cps.ReferencedAssemblies.AddRange(new[] { "System.dll", "System.Core.dll" }) var cp = new CSharpCodeProvider() var cr = cp.CompileAssemblyFromSource(cps, code) foreach (var err in cr.Errors) Console.WriteLine(err) if (!cr.Errors.HasErrors) { var m = cr.CompiledAssembly.GetType("Test").GetMethod("Run") var res = m.Invoke(null, new object[] { new[] { 1, 2, 3 } }) Console.WriteLine(res) } } } }
[Output] 6
Если значение var code указано прямо в Main, например: var code = @" using System // ... " то в code надо убрать
var cr = cp.CompileAssemblyFromSource(cps, Regex.Replace(code, "[ ]", " ")) иначе при компиляции будет ошибка: A namespace cannot directly contain members such as fields or methods.