2012-09-28 4 views
0

학습/실험을 위해 장난감 컴파일러를 만들었습니다. 여기 CSharpCodeProvider에 의해 생성 된 어셈블리와 상호 작용

는 일부 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?

특히 public delegate에 가입하거나 표준 출력을 캡처하는 데 관심이 있습니다. 그러나이 상황에서 유형이 서로 이야기 할 수있는 방법에 대한 일반적인 정보는 충분할 것입니다.

+2

당신은 기본 또는 인터페이스 –

+0

OK, 콜백 인터페이스를 사용할 수 있습니다 –

답변

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; 
    } 
}