//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace Emit
{
	/// <summary>
	/// Podsumowanie dla EmitMain.
	/// </summary>
	class EmitMain
	{
		static Type GenerateCode()
		{
			AppDomain currentDomain = AppDomain.CurrentDomain;

			// Utworzenie nowego podzespołu w AppDomain
			AssemblyName assemblyName = new AssemblyName();
			assemblyName.Name = "HelloAssembly";
			// Utworzenie AssemblyBuilder
			AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
			// Utworzenie ModuleBuilder
			ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("HelloModule");
			// Utworzenie TypeBuilder
			TypeBuilder typeBuilder = moduleBuilder.DefineType("HelloClass", TypeAttributes.Public);
			// Utworzenie MethodBuilder
			MethodBuilder methodBuilder = typeBuilder.DefineMethod("HelloWorld", MethodAttributes.Public, null, null);
			// Utworzenie generatora MSIL
			ILGenerator msil = methodBuilder.GetILGenerator();
			// Wygenerowanie kodu
			msil.EmitWriteLine("Witaj świecie!");
			msil.Emit(OpCodes.Ret);
			// Zwrócenie utworzonego typu
			return typeBuilder.CreateType();
		}
		static void Main(string[] args)
		{
			try
			{
				Type t = GenerateCode();
				object o = Activator.CreateInstance(t);
				MethodInfo mi = t.GetMethod("HelloWorld");
				Console.WriteLine(mi.Invoke(o, null));
			}
			catch(Exception e)
			{
				Console.WriteLine(e);
			}
		}
	}
}
