Tim Van Wassenhove

Passionate geek, interested in Technology. Proud father of two

26 Dec 2006

Exploring System.CodeDom

Today i wanted to experiment with System.CodeDom. This little program requests the user to input names for a namespace, class and method. It also asks the user to input the code that should go into the method body. Then it generates an assembly (test.dll) and creates a new appdomain in which the assembly is loaded… Finally it initializes an instance of the created class and calls the method…

static void Main(string[] args)
{
	string loopEnd = "";
	while (loopEnd != "X")
	{
		//string namespaceName = "MySpace";
		//string className = "MyClass";
		//string methodName = "MyMethod";
		//StringBuilder stringBuilder = new StringBuilder("System.Console.WriteLine(\"hihi\");");

		Console.Write("Enter namespace: ");
		string namespaceName = Console.ReadLine();
		Console.Write("Enter class: ");
		string className = Console.ReadLine();
		Console.Write("Enter method: ");
		string methodName = Console.ReadLine();

		StringBuilder stringBuilder = new StringBuilder();
		Console.WriteLine("Enter method body (X to stop)");
		string input = Console.ReadLine();
		while (input != "X")
		{
			stringBuilder.Append(input);
			input = Console.ReadLine();
		}

		CodeCompileUnit codeCompileUnit = new CodeCompileUnit();

		CodeAttributeDeclaration assemblyTitleAttribute = new CodeAttributeDeclaration("System.Reflection.AssemblyTitle");
		assemblyTitleAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression("A Generated Assembly")));
		codeCompileUnit.AssemblyCustomAttributes.Add(assemblyTitleAttribute);

		CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration();
		codeTypeDeclaration.Name = className;
		codeTypeDeclaration.IsClass = true;
		codeTypeDeclaration.Attributes = MemberAttributes.Public;

		CodeMemberMethod codeMemberMethod = new CodeMemberMethod();
		codeMemberMethod.Name = methodName;
		codeMemberMethod.Attributes = MemberAttributes.Public;
		codeMemberMethod.ReturnType = new CodeTypeReference(typeof(void));
		codeMemberMethod.Statements.Add(new CodeSnippetStatement(stringBuilder.ToString()));

		codeTypeDeclaration.Members.Add(codeMemberMethod);

		CodeNamespace codeNamespace = new CodeNamespace(namespaceName);
		codeNamespace.Types.Add(codeTypeDeclaration);
		codeCompileUnit.Namespaces.Add(codeNamespace);

		CompilerParameters compilerParameters = new CompilerParameters();
		compilerParameters.OutputAssembly = "test.dll";
		compilerParameters.GenerateExecutable = false;
		compilerParameters.GenerateInMemory = false;

		CSharpCodeProvider cSharpCodeProvider = new CSharpCodeProvider();
		CompilerResults compilerResults = cSharpCodeProvider.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);

		AppDomain appDomain = AppDomain.CreateDomain("new appdomain");
		Assembly assembly = appDomain.Load(compilerResults.CompiledAssembly.FullName);
		object instance = assembly.CreateInstance(namespaceName + "." + className);
		instance.GetType().InvokeMember(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, instance, null);
		AppDomain.Unload(appDomain);

		Console.WriteLine("Enter X to end (enter something different to continue)");
		loopEnd = Console.ReadLine();
	}
}