我为学习/实验制作了一个玩具编译器。
以下是编译一些C#代码的代码:
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
namespace ProgrammingSystem
{
public class Compiler
{
public Program Compile(Code code)
{
string template = @"
public class C
{
public static void Main(string[] args)
{
[[Source]]
}
}";
string source = template.Replace("[[Source]]", code.Source);
CodeDomProvider compiler = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.WarningLevel = 4;
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
CompilerResults r = compiler.CompileAssemblyFromSource(parameters, source);
foreach (var item in r.Output)
this.Fire(Output, item);
Assembly assembly = r.CompiledAssembly;
return new Program(assembly);
}
public event EventHandler<OutputEventArgs> Output;
}
}
以下是运行copmiled代码的代码:
using System;
using System.Reflection;
namespace ProgrammingSystem
{
public class Program
{
private System.Reflection.Assembly assembly;
public Program(System.Reflection.Assembly assembly)
{
this.assembly = assembly;
}
public event EventHandler<OutputEventArgs> ProgramOutput;
public void Run()
{
Type[] types = this.assembly.GetTypes();
Type programType = types[0];
MethodInfo programMainMethod = programType.GetMethod("Main");
programMainMethod.Invoke(null, new object[] { new string[] { } });
this.Fire(ProgramOutput, "hello");
}
}
}
我可以通过什么方式与CSharpCodeProvider?
在运行时生成的类型进行通信具体而言,我对订阅公共代表或捕获标准输出感兴趣,但是在类似情况下类型如何与彼此交谈的一般信息就足够了。
答案 0 :(得分:1)
我使用文档here来解决这个问题。
using System;
using System.Reflection;
namespace ProgrammingSystem
{
public class Program
{
private System.Reflection.Assembly assembly;
public Program(System.Reflection.Assembly assembly)
{
this.assembly = assembly;
}
public event EventHandler<OutputEventArgs> ProgramOutput;
public void Run()
{
Type programType = this.assembly.GetType("C");
object program = Activator.CreateInstance(programType);
EventInfo outputEvent = programType.GetEvent("output");
Delegate delegateInstance = Delegate.CreateDelegate(
outputEvent.EventHandlerType, this,
typeof(Program).GetMethod("OutputHandler", BindingFlags.NonPublic | BindingFlags.Instance));
MethodInfo addHandlerMethod = outputEvent.GetAddMethod();
addHandlerMethod.Invoke(program, new [] { delegateInstance });
programType.GetMethod("Run").Invoke(program, null);
}
private void OutputHandler(string s)
{
this.Fire(ProgramOutput, s);
}
}
}
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
namespace ProgrammingSystem
{
public class Compiler
{
public Program Compile(Code code)
{
string template = @"
using System;
public class C
{
public event Output output;
public void Run()
{
[[Source]]
output(""end"");
}
}
public delegate void Output(string s);
";
string source = template.Replace("[[Source]]", code.Source);
CodeDomProvider compiler = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.WarningLevel = 4;
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
CompilerResults r = compiler.CompileAssemblyFromSource(parameters, source);
foreach (var item in r.Output)
this.Fire(Output, item);
Assembly assembly = r.CompiledAssembly;
return new Program(assembly);
}
public event EventHandler<OutputEventArgs> Output;
}
}