I'm trying to create simple .net compiler for educational purposes. After parsing, scanning and building AST I'm generating .net assembly using Reflection.Emit.ILGenerator
.
Here is my sample code for assembly generation:
static void Main(string[] args)
{
string moduleName = "Test.exe";
AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(moduleName));
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
TypeBuilder typeBuilder = moduleBuilder.DefineType("Program", TypeAttributes.Public);
MethodBuilder mainMethod = typeBuilder.DefineMethod(
"Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), System.Type.EmptyTypes);
ILGenerator il = mainMethod.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Test!");
il.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
il.Emit(OpCodes.Ret);
typeBuilder.CreateType();
moduleBuilder.CreateGlobalFunctions();
assemblyBuilder.SetEntryPoint(mainMethod);
assemblyBuilder.Save(moduleName);
}
Everything works fine, this code generates executable with following class:
using System;
public class Program
{
public Program()
{
}
public static void Main()
{
Console.WriteLine("Test!");
}
}
Next I'm creating simple third party library with single class which builds to ThirdPartyLibrary.dll:
using System;
namespace ThirdPartyLibrary
{
public class MyPrint
{
public static void Print(string s)
{
Console.WriteLine("Third party prints: " + s);
}
}
}
Now I wish to replace Console.WriteLine
method call to MyPrint.Print
method call from my library and get result code something like:
using System;
using ThirdPartyLibrary;
public class Program
{
public Program()
{
}
public static void Main()
{
MyPrint.Print("Test!");
}
}
As far as I understand I must read my ThirdPartyLibrary.dll
file, then reflect it somehow to get all types from it and then it will be possible to use MyPrint
type. Finally I wish to be able to path references as myCompiler.exe arguments like using csc.exe.
So the questions are:
- How to do it?
- How all this named? (I can't understand what to google)
- May be I should use some other frameworks, instead of Reflection to do all this?
- Any other suggestions...