using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;

namespace Howest.CodeDom.Types
{
	class Program
	{
		static void Main(string[] args)
		{
			CodeTypeDeclaration type = new CodeTypeDeclaration("Person");
			CodeMemberField field = new CodeMemberField();
			field.Type = new CodeTypeReference(typeof(string));
			field.Name = "_name";
			field.InitExpression = new CodePrimitiveExpression("John Doe");
			type.Members.Add(field);
			CodeMemberProperty prop = new CodeMemberProperty();
			prop.Name = "Name";
			prop.GetStatements.Add(
				new CodeMethodReturnStatement(
					new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name)));
			prop.SetStatements.Add(
				new CodeAssignStatement(
					new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name), 
					new CodePropertySetValueReferenceExpression()));
			prop.Type = new CodeTypeReference(typeof(string));
			type.Members.Add(prop);
			CodeMemberMethod method = new CodeMemberMethod();
			method.Name = "SayHello";
			CodeBinaryOperatorExpression strConstruct = new CodeBinaryOperatorExpression(
				new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), prop.Name), 
				CodeBinaryOperatorType.Add, 
				new CodePrimitiveExpression(" says hello!"));
			CodeMethodInvokeExpression cw = new CodeMethodInvokeExpression(
				new CodeTypeReferenceExpression(new CodeTypeReference(typeof(Console))),
				"WriteLine",
				strConstruct);
			method.Statements.Add(cw);
			type.Members.Add(method);
			CodeNamespace ns = new CodeNamespace("CodeDomPerson.Data");
			ns.Imports.Add(new CodeNamespaceImport("System"));

			ns.Types.Add(type);

			CodeDomProvider provider = new CSharpCodeProvider();
			StreamWriter wr = new StreamWriter("Person.cs");
			CodeGeneratorOptions opts = new CodeGeneratorOptions();
			opts.BracingStyle = "C";
			provider.GenerateCodeFromNamespace(ns, wr, opts);
			wr.Close();
		}
	}
}
