Fluent CodeDOM should make it faster and more intuitive to generate code with CodeDOM, because it is designed to look a little bit like real code.

But I'm a fan of little talking and more coding so:


Sample 1: First Sample:

- Download the Zip with the FluentCodeDOM DLLs and store it somewhere on your disc
- Create a new Console Project
- Add a reference to FluentCodeDom.dll
- Add following code:


using System;
using System.Collections.Generic;
using System.Text;
using FluentCodeDom;
using System.CodeDom;
using System.Reflection;

namespace FluentCodeDom.Sample1
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeCompileUnit compileUnit = new FluentCodeCompileUnit()
                .Namespace("Sample1")
                    .Class("Program")
                        .Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
                            .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
                        .EndMethod
                    .EndClass
                .EndNamespace
            .EndFluent();

            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
            assembly.GetType("Sample1.Program").GetMethod("Main").Invoke(null, new object[] { null });
        }
    }
}


I think it's not quite too difficult to notice what the generated code does right? So I'm gonna explain the generating code in a little bit more detail.
You always start out with a FluentCodeCompileUnit. With .Namespace, .Class, .Method and so on you define namespaces, classes, methods respectively.
You also surely notice that all elements end with an ".End" property. This property means that it goes one up one "fluent level", so here for example from Body to Method, from Method to Class, from Class to Namespace and from the Namespace to CodeCompileUnit.
At the end there is a EndFluent() method call.Tthis means its leave the "Fluent Mode" and returns a CodeDOM object, in this case the FluentCodeCompileUnit.


Sample 2: Real World Scenario:

Ok this code looks nice, but in real world there are many ifs and loops and stuff so lets get into a more realistic scenario.

In this sample I want to generate a dummy class for any interface which tells me with witch parameters the functions are called. This is particulary useful for unit testing.

using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.Reflection;
using FluentCodeDom;
using Microsoft.CSharp;

namespace FluentCodeDom.Sample2
{
    public class Program
    {
        static void Main(string[] args)
        {
            ISample sample = ImplentInterface<ISample>();
            sample.Method1("Hello");
            sample.Method2(32, 65);

            Console.ReadLine();
        }

        private static TInterface ImplentInterface<TInterface>()
        {
            Type interfaceType = typeof(TInterface);
            FluentCodeNamespace ns = new FluentCodeCompileUnit().Namespace("Sample2");

            // public class <Interface>Test : <Interface>
            string typeName = string.Format("{0}Test", interfaceType.Name);
            var type = ns.Class(typeName).Inherits(interfaceType);

            foreach (MethodInfo methodInfo in interfaceType.GetMethods())
            {
                // Console.WriteLine("<Method> called with Parameters:")
                var method =
                    type.Method(MemberAttributes.Public, methodInfo.Name)
                        .CallStatic(typeof(Console), "WriteLine", Expr.Primitive(string.Format("{0} called with parameters:", methodInfo.Name)));

                foreach (ParameterInfo paramInfo in methodInfo.GetParameters())
                {
                    method.Parameter(paramInfo.ParameterType, paramInfo.Name);

                    // Console.WriteLine("<ParamName>: <Value>")
                    method.CallStatic(typeof(Console), "WriteLine",
                            Expr.CallStatic(typeof(string), "Format",
                                Expr.Primitive(string.Format("{0}: {1}", paramInfo.Name, "{1}")),
                                Expr.CallMember(Expr.Arg(paramInfo.Name), "ToString")
                                )
                            );
                }
            }

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();

            // Display Code
            string code = Helper.CodeDomHelper.GenerateCodeAsString(compileUnit, new CSharpCodeProvider());
            Console.WriteLine(code);
            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);

            return (TInterface)assembly.GetType(string.Format("Sample2.{0}", typeName))
                .GetConstructor(Type.EmptyTypes)
                .Invoke(new object[] { });
        }
    }

    public interface ISample
    {
        void Method1(string strParam);

        void Method2(int aNumber, float aFloat);
    }
}

Sample 3: Extending Fluent CodeDOM:

Well, FluentCodeDOM has many functions built-in, but in some scenarios you might need method stumps - or you might have written your own CodeDom Expressions, so how is it about extending FluentCodeDOM?
It may sounds a little bit stupid fist, but lets do it with extension methods!!!

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.CodeDom;
using FluentCodeDom;

namespace FluentCodeDom.Sample3
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeCompileUnit compileUnit = new FluentCodeCompileUnit()
                .Namespace("Sample3")
                    .Class("Program")
                        .Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
                            .ConsoleWriteLine(Expr.Primitive("Hello Fluent CodeDom")).UserData("Key", "Value")
                        .EndMethod
                    .EndClass
                .EndNamespace
            .EndFluent();

            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
            assembly.GetType("Sample3.Program").GetMethod("Main").Invoke(null, new object[] { null });
        }
    }

    public static class FluentCodeDomExtensions
    {
        /// <summary>
        /// Adds a Console.WriteLine Statement.
        /// </summary>
        /// <param name="textExpr"></param>
        /// <returns></returns>
        public static TThis ConsoleWriteLine<TParent, TThis>(this FluentCodeBody<TParent, TThis> body, params CodeExpression[] textExpr)
            where TThis : FluentCodeBody<TParent, TThis>
        {
            return body.CallStatic(typeof(Console), "WriteLine", textExpr);
        }

        /// <summary>
        /// Adds a keyValuePair the user data of the last added statement.
        /// </summary>
        /// <returns></returns>
        public static TThis UserData<TParent, TThis>(this FluentCodeBody<TParent, TThis> body, object key, object value)
            where TThis : FluentCodeBody<TParent, TThis>
        {
            ICodeBodyProvider bodyProvider = FluentCodeBody<TParent, TThis>.GetBodyProvider(body);
            if (bodyProvider.Statements.Count == 0)
                throw new InvalidOperationException("No statement till now added.");

            bodyProvider.Statements[bodyProvider.Statements.Count - 1].UserData.Add(key, value);

            return (TThis)(object)body;
        }
    }
}


The first statement is a simplification for the (for testing purposes) often used Console.WriteLine. The second statement adds a KeyValuePair to the UserData of the last statement added.

You surely noticed the FluentCodeBody<TParent, TThis>.GetBodyProvider(body) Method. All elements in CodeDOM have some static methods to access the internal wrapped types. This retrieves the code body so that I can acess the statements inside my method.


Sample 4: Linq2CodeDOM:

All this Stuff until now is pretty good, but all this Expr Stuff is a little bit confusing, so lets do some COOL Stuff. You surely had your expieriences with the linq expressions used in LinqToSQL and the Entity Framework to generate SQL Code. So why don't use this Stuff to generate CodeDOM Expressions?

Well I'm a very lazy man (like every programmer), so I used a already existing solution from another good CodeDOM Project here on CodePlex, called Linq2CodeDOM that already implemented this. I only wrote a small wrapper for this:

- Reference Linq2CodeDOM.dll
- Reference FluentCodeDom.Linq.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using FluentCodeDom;
using Microsoft.CSharp;

namespace FluentCodeDom.Sample4
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeCompileUnit compileUnit = new FluentCodeCompileUnit()
                .Namespace("Sample4")
                    .Class("Program")
                        .Method("Test")
                            .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Test"))
                            .If(Expr.Op(Expr.Primitive(5), CodeBinaryOperatorType.GreaterThan, Expr.Primitive(3)))
                            .EndIf
                        .EndMethod

                        .Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
                            .Stmt(ExprLinq.Expr(() => Console.WriteLine("Hello Linq2CodeDOM")))
                            .Declare(typeof(int), "random", ExprLinq.Expr(() => new Random().Next(10)))
                            .If((int random) => random <= 5)
                                .Stmt(ExprLinq.Expr(() => Console.WriteLine("Smaller or equal to 5.")))
                            .Else
                                .Stmt(ExprLinq.Expr(() => Console.WriteLine("Bigger than 5.")))
                            .EndIf
                        .EndMethod
                    .EndClass
                .EndNamespace
            .EndFluent();

            Console.WriteLine(Helper.CodeDomHelper.GenerateCodeAsString(compileUnit, new CSharpCodeProvider()));
            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
            assembly.GetType("Sample4.Program").GetMethod("Main").Invoke(null, new object[] { null });
        }
    }
}


Sample 5: Emulators:

Well CodeDOM is very mighty but it doesn't support many usefull language features like foreach, while and usings just for calling a small number of missing features.

One way to solve this problem is to write your own expressions like it is done in Linq2CodeDOM, but in this case you must write support for each CodeProvider yourself and if someone writes his own MSILCodeProvider or maybe FSharpCodeProvider this will not work with your generated code. The solution I used for FluentCodeDOM is that I emulated features like foreach, using and While with other CSharp Statements. For example, the while is emulated with a for loop and the using with a try-finally - block. In further releases I will include support for the Linq2CodeDOM expressions to allow you writing nicer looking code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using FluentCodeDom;
using Microsoft.CSharp;

namespace FluentCodeDom.Sample5
{
    class Program
    {
        static void Main(string[] args)
        {
            var ns = new FluentCodeCompileUnit().Namespace("Sample5");
            ns.Class(MemberAttributes.Public | MemberAttributes.Static, "Program")
                .Method(MemberAttributes.Public | MemberAttributes.Static, "ForArrayTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("ForArrayTest:"))
                    .Declare(typeof(string[]), "sArr", Expr.NewArray(typeof(string), Expr.Primitive(2)))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(0)), Expr.Primitive("Hallo1"))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(1)), Expr.Primitive("Hallo2"))

                    .ForArray("i", Expr.Var("sArr"))
                        .CallStatic(typeof(Console), "WriteLine", Expr.ArrayIndex(Expr.Var("sArr"), Expr.Var("i")))
                    .EndFor

                .EndMethod

                .Method(MemberAttributes.Public | MemberAttributes.Static, "ForeachTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("ForeachTest:"))
                    .Declare(typeof(string[]), "sArr", Expr.NewArray(typeof(string), Expr.Primitive(2)))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(0)), Expr.Primitive("Hallo1"))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(1)), Expr.Primitive("Hallo2"))

                    .ForeachEmu(typeof(string), "s", Expr.Var("sArr"))
                        .CallStatic(typeof(Console), "WriteLine", Expr.Var("s"))
                    .EndForeach
                .EndMethod

                .Method(MemberAttributes.Public | MemberAttributes.Static, "WhileTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("WhileTest:"))
                    .Declare(typeof(int), "a", Expr.Primitive(1))
                    .WhileEmu(Expr.Op(Expr.Var("a"), CodeBinaryOperatorType.LessThanOrEqual, Expr.Primitive(10)))
                        .CallStatic(typeof(Console), "WriteLine", Expr.CallStatic(typeof(string), "Format", Expr.Primitive("Value: {0}"), Expr.Var("a")))
                        .Set(Expr.Var("a"), Expr.Op(Expr.Var("a"), CodeBinaryOperatorType.Add, Expr.Primitive(1)))
                    .EndWhile
                .EndMethod
            .EndFluent();

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();
            Console.WriteLine(Helper.CodeDomHelper.GenerateCodeAsString(compileUnit, new CSharpCodeProvider()));

            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
            assembly.GetType("Sample5.Program").GetMethod("ForArrayTest").Invoke(null, new object[] { });
            assembly.GetType("Sample5.Program").GetMethod("ForeachTest").Invoke(null, new object[] { });
            assembly.GetType("Sample5.Program").GetMethod("WhileTest").Invoke(null, new object[] { });
        }
    }
}

Other Samples:

This were just a few samples to let your see how you can write code with FluentCodeDOM. To get an a little bit deeper look into what Fluent CodeDOM currently can do, I add the Unit Tests below. You can also browse the samples and the units tests from SourceControl.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentCodeDom;
using System.CodeDom;
using FluentCodeDom.Helper;
using FluentCodeDom.Linq;
using System.IO;
using System.Reflection;

namespace FluentCodeDom.Test
{
    public class DeclarationTest
    {
        public static void DefintionTest()
        {
            var fluent = new FluentCodeCompileUnit();
            CodeCompileUnit compileUnit = fluent
                .Namespace("Test.FluentCodeDom.Test")
                    .Import("System")
                    .Import("System.Text")

                    .Class(MemberAttributes.Public, "StringModifier")
                        .Constructor()
                        .EndConstructor
                       
                        .Field(typeof(int), "_fld").EndField
                        .Field(MemberAttributes.Private, typeof(int), "_field1").EndField
                        .Field(MemberAttributes.Private, typeof(DateTime), "_now").EndField
                        .Field(typeof(DateTime), "_now2").EndField

                        .Field(typeof(int), "_intValue").EndField
                        .Property(MemberAttributes.Public, typeof(int), "IntValue")
                            .Get
                                .Return(Expr.Var("_intValue"))
                            .EndGet
                            .Set
                                .Set(Expr.Var("_intValue"), Expr.Value())
                            .EndSet
                        .EndProperty

                        .Method(MemberAttributes.Public, "OutMethod").Parameter(typeof(int), "outParam")
                            .Set(Expr.Arg("outParam"), Expr.Primitive(55))
                        .EndMethod

                        .Method(MemberAttributes.Public, "HelloWorld")
                            .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hallo Welt"))
                            .CallStatic(typeof(Console), "ReadLine")
                        .EndMethod

                        .Method("StringSplit").Parameter(typeof(string), "s").Parameter(typeof(char), "seperationChar").ReturnType(typeof(string))
                            .Declare(typeof(string[]), "stringArr", Expr.CallMember(Expr.Arg("s"), "Split", Expr.Arg("seperationChar")))
                           
                            .If(Expr.Op(Expr.Primitive(5), CodeBinaryOperatorType.ValueEquality, Expr.Primitive(10)))
                                .Declare(typeof(int), "abc")
                                .Set(Expr.Var("abc"), Expr.Primitive(5))
                            .Else
                                .If(Expr.Primitive(false))
                                    .Call("HelloWorld")
                                .EndIf

                                .Declare(typeof(int[]), "array", Expr.NewArray(typeof(int), Expr.Primitive(5) ))
                                .ForArray("i", Expr.Var("array"))
                                .EndFor
                            .EndIf

                            .Return(Expr.ArrayIndex(Expr.Var("stringArr"), Expr.Primitive(0)))
                        .EndMethod
                    .EndClass

                    .Enum(MemberAttributes.Public, "SuperEnum")
                        .Value("Unit", 1).EndValue
                        .Value("Testing", 2).EndValue
                        .Value("Sucks").EndValue
                    .EndEnum
                .EndNamespace
            .EndFluent();

            TestGenerated(compileUnit);
        }

        public static void ConstructorTest()
        {
            FluentCodeCompileUnit compileUnit = new FluentCodeCompileUnit();
            compileUnit.Namespace("TestNamespace")
                .Class("AClass").Inherits("BaseClass")
                    .Constructor(MemberAttributes.Public)
                        .BaseArgs()
                    .EndConstructor

                    .Constructor(MemberAttributes.Public).Parameter(typeof(int), "IntArg")
                        .ThisArgs(Expr.Arg("IntArg"), Expr.Primitive("Hello"))
                    .EndConstructor

                    .Constructor(MemberAttributes.Public).Parameter(typeof(int), "IntArg").Parameter(typeof(string), "StringArg")
                        .BaseArgs(Expr.Arg("StringArg"))
                    .EndConstructor
                .EndClass

                .Class("BaseClass")
                    .Constructor(MemberAttributes.Public)
                    .EndConstructor

                    .Constructor(MemberAttributes.Public).Parameter(typeof(string), "TextToPrint")
                        .CallStatic(typeof(Console), "WriteLine", Expr.Arg("TextToPrint"))
                    .EndConstructor
                .EndClass
            .EndFluent();

            Assembly assembly = TestGenerated(compileUnit.EndFluent());

            object instance = GetClassInstance("TestNamespace.AClass", assembly);
            instance.GetType().GetConstructor(new Type[] { typeof(int)}).Invoke(instance, new object[] { 32 });
        }

        public static void EnumTest()
        {
            FluentCodeCompileUnit compileUnit = new FluentCodeCompileUnit();
            compileUnit.Namespace("TestNamespace")
                .Enum("TestEnum").CustomAttribute(typeof(FlagsAttribute))
                    .Value("Value1", Expr.Primitive(1)).EndValue
                    .Value("Value2", Expr.Primitive(2)).EndValue
                    .Value("Value3", Expr.Primitive(4)).EndValue
                .EndEnum
            .EndFluent();

            TestGenerated(compileUnit.EndFluent());
        }

        public static void ClassDeclaration()
        {
            CodeTypeDeclaration cls = new FluentCodeClass()
                .Method("TestMethod").Attributes(MemberAttributes.Public).Parameter(typeof(string), "parameter1").ReturnType(typeof(int))
                    .Declare(typeof(DateTime), "supervar", Expr.Primitive(5))
                    .Call("method")
                    .Return()
                .EndMethod
            .EndFluent();

            var type2 = new FluentCodeClass().Name("MathType");
            type2.Method("Add").Parameter(typeof(int), "IntA").Parameter(typeof(int), "IntB")
                .Return((int a, int b) => a + b)
            .EndFluent();

            type2.Method("Subtract").Parameter(typeof(int), "IntA").Parameter(typeof(int), "IntB")
                .Return((int a, int b) => a - b)
            .EndFluent();

            var compileUnit = new CodeCompileUnit();
            var ns = new CodeNamespace();
            ns.Imports.Add(new CodeNamespaceImport("Test"));
            compileUnit.Namespaces.Add(ns);

            TestGenerated(compileUnit);
        }

        public static void TryCatchTest()
        {
            var ns = new FluentCodeCompileUnit().Namespace("TestNamespace")
                .Import("System");

            FluentCodeClass type = ns.Class(MemberAttributes.Public, "TryCatchClass");

            type.Method(MemberAttributes.Public, "TryCatchMethod")
                .Try
                    .Throw(Expr.New(typeof(Exception), Expr.Primitive("Evil Exception")))
                .Catch(typeof(Exception), "ex")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Catch Block"))
                .Finally
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Finally Block"))
                .EndTry
            .EndMethod.EndFluent();

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();
            TestGenerated(compileUnit);
        }

        public static void LinqTest()
        {
            var ns = new FluentCodeCompileUnit().Namespace("TestNamespace");
            ns.Class("AClass")
                .Method(MemberAttributes.Public, "LinqTest").ReturnType(typeof(bool))
                    .Declare(typeof(int), "a", Expr.Primitive(5))
                    .Declare(typeof(int), "b", Expr.Primitive(6))
                    .If((int a, int b) => a > b)
                        .Declare(typeof(string), "text", Expr.Primitive("A is bigger than B"))
                        .Stmt((string text) => Console.WriteLine(text))
                        .Stmt(ExprLinq.Expr(() => Console.Read()))
                    .Else
                        .Declare(typeof(string), "text", Expr.Primitive("B is bigger or equal A"))
                        .Stmt((string text) => Console.WriteLine(text))
                    .EndIf

                    .Return((int a, int b) => a > b)
                .EndMethod
            .EndFluent();

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();
            Assembly assembly = TestGenerated(compileUnit);

            object instance = GetClassInstance("TestNamespace.AClass", assembly);
            instance.GetType().GetMethod("LinqTest").Invoke(instance, new object[] { });
        }

        public static void LoopTest()
        {
            var ns = new FluentCodeCompileUnit().Namespace("TestNamespace");
            ns.Class("AClass")
                .Method(MemberAttributes.Public, "ForArrayTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("ForArrayTest:"))
                    .Declare(typeof(string[]), "sArr", Expr.NewArray(typeof(string), Expr.Primitive(2)))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(0)), Expr.Primitive("Hallo1"))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(1)), Expr.Primitive("Hallo2"))

                    .ForArray("i", Expr.Var("sArr"))
                        .CallStatic(typeof(Console), "WriteLine", Expr.ArrayIndex(Expr.Var("sArr"), Expr.Var("i")))
                    .EndFor
                .EndMethod

                .Method(MemberAttributes.Public, "ForeachTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("ForeachTest:"))
                    .Declare(typeof(string[]), "sArr", Expr.NewArray(typeof(string), Expr.Primitive(2)))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(0)), Expr.Primitive("Hallo1"))
                    .Set(Expr.ArrayIndex(Expr.Var("sArr"), Expr.Primitive(1)), Expr.Primitive("Hallo2"))

                    .ForeachEmu(typeof(string), "s", Expr.Var("sArr"))
                        .CallStatic(typeof(Console), "WriteLine", Expr.Var("s"))
                    .EndForeach
                .EndMethod

                .Method(MemberAttributes.Public, "WhileTest")
                    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("WhileTest:"))
                    .Declare(typeof(int), "a", Expr.Primitive(1))
                    .WhileEmu(Expr.Op(Expr.Var("a"), CodeBinaryOperatorType.LessThanOrEqual, Expr.Primitive(10)))
                        .CallStatic(typeof(Console), "WriteLine", Expr.CallStatic(typeof(string), "Format", Expr.Primitive("Value: {0}"), Expr.Var("a")))
                        .Set(Expr.Var("a"), Expr.Op(Expr.Var("a"), CodeBinaryOperatorType.Add, Expr.Primitive(1)))
                    .EndWhile
                .EndMethod
            .EndFluent();

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();
            Assembly assembly = TestGenerated(compileUnit);

            object instance = GetClassInstance("TestNamespace.AClass", assembly);
            instance.GetType().GetMethod("ForArrayTest").Invoke(instance, new object[] { });
            instance.GetType().GetMethod("ForeachTest").Invoke(instance, new object[] { });
            instance.GetType().GetMethod("WhileTest").Invoke(instance, new object[] { });
        }

        private static object GetClassInstance(string className, Assembly assembly)
        {
            Type aType = assembly.GetType(className);
            object instance = aType.GetConstructor(new Type[] { }).Invoke(new object[] { });

            return instance;
        }

        public static void UsingTest()
        {
            string executingAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
            string path = System.IO.Path.GetDirectoryName(executingAssemblyPath) + "\\..\\..\\test.txt";

            var ns = new FluentCodeCompileUnit().Namespace("TestNamespace");
            ns.Class("AClass")
                .Method(MemberAttributes.Public, "UsingTest")
                    .Declare(typeof(System.IO.FileStream), "fs", Expr.CallStatic(typeof(System.IO.File), "OpenRead", Expr.Primitive(path)))
                    .UsingEmu(Expr.Var("fs"))
                        .UsingEmu(Expr.Declare(typeof(StreamReader), "sr", Expr.New(typeof(StreamReader), Expr.Var("fs"))))
                            .CallStatic(typeof(Console), "WriteLine", Expr.CallMember(Expr.Var("sr"), "ReadToEnd"))
                        .EndUsing
                    .EndUsing
                .EndMethod
            .EndFluent();

            CodeCompileUnit compileUnit = ns.EndNamespace.EndFluent();
            Assembly assembly = TestGenerated(compileUnit);

            object instance = GetClassInstance("TestNamespace.AClass", assembly);
            instance.GetType().GetMethod("UsingTest").Invoke(instance, new object[] { });
        }

        public static System.CodeDom.Compiler.CodeDomProvider CodeDomProvider = new Microsoft.CSharp.CSharpCodeProvider();

        private static Assembly TestGenerated(CodeCompileUnit compileUnit)
        {
            string code = CodeDomHelper.GenerateCodeAsString(compileUnit, DeclarationTest.CodeDomProvider);
            Console.Write(code);

            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            Assembly assembly = CodeDomHelper.CompileInMemory(new CodeCompileUnit[] { compileUnit });

            sw.Stop();
            Console.WriteLine("Required Time to compile {0} milliseconds", sw.ElapsedMilliseconds);
            sw.Reset();

            return assembly;
        }
    }
}

Last edited Mar 26, 2011 at 10:09 PM by Desert_Fox, version 4

Comments

No comments yet.