|
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.