Click here to Skip to main content
15,886,519 members
Articles / Programming Languages / C#

Dynamic Assemblies

Rate me:
Please Sign up or sign in to vote.
2.94/5 (10 votes)
24 Aug 2008CPOL8 min read 37.5K   636   30  
Creating Dynamic assemblies in C#
using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;

namespace DynamicAssemblyDemo
{
    class DynamicAssemblyCreator
    {
        CodeCompileUnit codeCompileUnit;
        CodeTypeDeclaration bookShopRuleClass;
        List<Rule> rules;

        public List<Rule> Rules
        {
            get { return rules; }
            set { rules = value; }
        }

 
        public void Intialize()
        {
            codeCompileUnit = new CodeCompileUnit();
        }

        public void CreatClass()
        {
            // Declare a new namespace
            CodeNamespace codeNamespace = new CodeNamespace("DynamicAssemblyDemo.DynamicAssembly");
            // Add the new namespace to the compile unit.
            codeCompileUnit.Namespaces.Add(codeNamespace);

            // Add the new namespace import for the System namespace.
            codeNamespace.Imports.Add(new CodeNamespaceImport("System"));

            // Declare a new type called BookShopRuleAssembly.
            bookShopRuleClass = new CodeTypeDeclaration("BookShopRuleClass");
            
            // Add the new type to the namespace type collection.
            codeNamespace.Types.Add(bookShopRuleClass);

            //Adding a comment
            bookShopRuleClass.Comments.Add(new CodeCommentStatement("This is a dynamically created class for Book Shop dynamic Requirements, Class name 'BookShopRuleClass'" + Environment.NewLine + "Creator : Tharindu Patikirikorala"));
            
            SetFields();
            SetMethods();

        }

        private void SetMethods()
        {
            for (int i = 0; i < rules.Count; i++)
            {
                string name = rules[i].Name + Meta.sep +rules[i].Item;
                Type t = Type.GetType(rules[i].ReturnType);
                CodeTypeReference typeRef = new CodeTypeReference(t);
                CodeMemberMethod method =  this.SetMethod(name, typeRef, rules[i].Body);
                bookShopRuleClass.Members.Add(method);
            }
           
        }

        /// <summary>
        /// Creating a method to be added to bookShopRuleClass
        /// </summary>
        /// <param name="name"></param>
        /// <param name="returnType"></param>
        /// <param name="methodBody"></param>
        /// <returns></returns>
        private CodeMemberMethod SetMethod(string name, CodeTypeReference returnType, string methodBody)
        {
            CodeMemberMethod method = new CodeMemberMethod();
            method.Name = name;
            CodeSnippetStatement statement = new CodeSnippetStatement(methodBody); // adding method body
            method.ReturnType = returnType;
            method.Statements.Add(statement); // adding the statment in to the method
            method.Attributes = MemberAttributes.Public;
            return method;
        }

        /// <summary>
        /// Adding the fields of the bookShopRuleClass.
        /// </summary>
        private void SetFields()
        {

            // adding the category field
            CodeMemberField  tempField = GetFieldCode(Meta.category, new CodeTypeReference(typeof(System.String)));
			bookShopRuleClass.Members.Add(tempField);

            tempField.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "Fields and Properties"));

            // adding the subCategory field
            tempField = GetFieldCode(Meta.subCategory, new CodeTypeReference(typeof(System.String)));
            bookShopRuleClass.Members.Add(tempField);

            // adding the price field
            tempField = GetFieldCode(Meta.price, new CodeTypeReference(typeof(System.Double)));
            bookShopRuleClass.Members.Add(tempField);

            // adding the price field
            tempField = GetFieldCode(Meta.quantity, new CodeTypeReference(typeof(System.Int64)));
            bookShopRuleClass.Members.Add(tempField);

            // adding the item field
            tempField = GetFieldCode(Meta.item, new CodeTypeReference(typeof(System.String)));
            tempField.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "End"));
            bookShopRuleClass.Members.Add(tempField);
            

        }

        /// <summary>
        /// Make a public field thats is a member of bookShopRuleClass
        /// </summary>
        /// <param name="name"></param>
        /// <param name="fieldType"></param>
        /// <returns></returns>
        private CodeMemberField GetFieldCode(string name, CodeTypeReference fieldType)
        {
            CodeMemberField field = new CodeMemberField();
            field.Name = name;
            field.Attributes = MemberAttributes.Public;
            field.Type = fieldType;
            return field;
        }


        /// <summary>
        /// Compile Code, and getting the CompilerResults which will give us the copiled assembly
        /// </summary>
        /// <returns>CompilerResults</returns>
        public CompilerResults CompileCode()
        {
            CompilerResults cr = null;

            try
            {
                // options when generating source code
                CodeGeneratorOptions options = new CodeGeneratorOptions();

                //Verbatim ordering turned on - code generated in the order added
                options.VerbatimOrder = true;
                //String for code indentation
                options.IndentString = "     ";
                options.BlankLinesBetweenMembers = false;

                CodeDomProvider provider = new CSharpCodeProvider();

                string dllFile ="BookShopRuleAssembly" + ".dll";

                //writing the source code to the Disk, check the bin folder.
                IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter("BookShopRuleAssemblySource.cs", false), "    ");
                // Generate source code using the code generator.
                provider.GenerateCodeFromCompileUnit(this.codeCompileUnit, tw, options);
                tw.Close();

                // Configure a CompilerParameters that links System.dll
                // and produces the specified dll file.
                String[] referenceAssemblies = { "System.dll" };

                CompilerParameters cp = new CompilerParameters(); // provide addition infomation needed by the compiler

                cp.ReferencedAssemblies.AddRange(referenceAssemblies);
                cp.IncludeDebugInformation = false;
                cp.OutputAssembly = dllFile;
                cp.GenerateInMemory = true;
                
                // Generate an executable if true, DLL otherwise
                cp.GenerateExecutable = false;

                // Invoke compilation using CodeCompileUnit object
                cr = provider.CompileAssemblyFromDom(cp , this.codeCompileUnit);


                if (cr.Errors.Count > 0)
                {
                    // Display compilation errors.
                    Console.WriteLine("Errors building {0} into {1}",dllFile, cr.PathToAssembly);
                    foreach (CompilerError ce in cr.Errors)
                    {
                        Console.WriteLine("  {0}", ce.ToString());
                        Console.WriteLine();
                    }
                }
                else
                {
                    Console.WriteLine("Source {0} built into {1} successfully.",
                        dllFile, cr.PathToAssembly);
                }


            }
            catch (Exception ex)
            {
           
            }

            // Return the results of compilation.
            return cr;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Sri Lanka Sri Lanka
PhD, BSc(Eng), MCP (Web Development)

Comments and Discussions