导航

代碼生成技術範例

Posted on 2008-06-03 12:24  满延平  阅读(253)  评论(1)    收藏  举报

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

namespace TestGenerateCode
{
    class Program
    {
        static void Main(string[] args)
        {
            string strCode = GenerateCode("CodeGuru.DynamicCode", "ScriptType", "Test t=new Test();t.Testid=\"test\";return t.Testid;");
            CompileInMemory(strCode);
            Test.Test t = new Test.Test();
            CodeGuru.DynamicCode.ScriptType ji = new CodeGuru.DynamicCode.ScriptType();
            Console.WriteLine(ji.SayHello(t));
            Console.ReadLine();
        }

        public static CodeCompileUnit CreateExecutionClass(string typeNamespace,string typeName,string scriptBody)
        {
            // 创建CodeCompileUnit以包含代码
            CodeCompileUnit ccu = new CodeCompileUnit(); // 分配需要的命名空间
            CodeNamespace cns = new CodeNamespace(typeNamespace);
            cns.Imports.Add(new CodeNamespaceImport("System"));
            cns.Imports.Add(new CodeNamespaceImport("Test"));
            ccu.Namespaces.Add(cns); // 创建新的类声明
            CodeTypeDeclaration parentClass = new CodeTypeDeclaration(typeName);
            cns.Types.Add(parentClass); // 创建获得一个参数并返回一个字符串的SayHello方法
            CodeMemberMethod method = new CodeMemberMethod();
            method.Name = "SayHello";
            method.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression arg = new CodeParameterDeclarationExpression("Test", "inputMessage");
            method.Parameters.Add(arg);
            method.ReturnType = new CodeTypeReference(typeof(string)); // 添加方法实体需要的代码
            CodeSnippetStatement methodBody = new CodeSnippetStatement(scriptBody);
            method.Statements.Add(methodBody);
            parentClass.Members.Add(method);
            return ccu;
        }

        public static string GenerateCode(string typeNamespace,string typeName,string scriptBody)
        {
            // 调用我们前面的方法创建CodeCompileUnit
            CodeCompileUnit ccu = CreateExecutionClass(typeNamespace,
            typeName, scriptBody);
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BlankLinesBetweenMembers = false;
            options.IndentString = "\t";
            StringWriter sw = new StringWriter();
            try
            {
                provider.GenerateCodeFromCompileUnit(ccu, sw, options);
                sw.Flush();
            }
            finally
            {
                sw.Close();
            }
            return sw.GetStringBuilder().ToString();
        }

        static Assembly CompileInMemory(string code)
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters options = new CompilerParameters();
            options.IncludeDebugInformation = false;
            options.GenerateExecutable = false;
            options.GenerateInMemory = true;
            options.OutputAssembly="DataModel.dll";
            options.ReferencedAssemblies.Add(@"D:\myproject\TestGenerateCode\TestGenerateCode\bin\Debug\Test.dll");
            CompilerResults results = provider.CompileAssemblyFromSource(options, code);
            provider.Dispose();
            Assembly generatedAssembly = null;
            if (results.Errors.Count == 0)
            {
                generatedAssembly = results.CompiledAssembly;
            }

            if (results != null && results.Errors.Count > 0)
            {
                string strMsg = string.Empty;
                foreach (CompilerError e in results.Errors)      //print out result
                {
                    if (strMsg == string.Empty)
                        strMsg = e.ToString();
                    else
                        strMsg = strMsg + ";" + e.ToString();
                }
            }
            return generatedAssembly;
        }

    }
}