天天看點

簡單的CodeDOM示例

原文 http://blog.sunmast.com/sunmast/archive/2004/08/24/870.aspx

using System;

using System.CodeDom;

using System.CodeDom.Compiler;

using System.IO;

using System.Reflection;

using System.Text;

using Microsoft.CSharp;

namespace Sunmast.Sample.CodeDom

{

 class Entry

 {

  [STAThread]

  static void Main(string[] args)

  {

   // 建立CodeDOM

   CodeCompileUnit codeDom = GenerateCodeDom();

   // 編譯為可用的Assembly

   // 這裡使用C#代碼,實際上任何繼承了CodeDomProvider類的Provider都行

   // 是以可以換成Microsoft.VisualBasic.VBCodeProvider

   Assembly assembly = ComplieCodeDomToAssembly(codeDom,new CSharpCodeProvider());

   // 動态調用assembly

   if(assembly != null)

   {

    InvokeMethodsFromAssembly(assembly);

   }

   Console.ReadLine();

  }

  static CodeCompileUnit GenerateCodeDom()

  {

   // 命名空間

   CodeNamespace cn = new CodeNamespace("Sunmast.Sample.CodeDom");

   cn.Imports.Add(new CodeNamespaceImport("System"));

   // 建立新的類型

   CodeTypeDeclaration ctd = new CodeTypeDeclaration("SunmastClass");

   ctd.IsClass = true;

   ctd.TypeAttributes = TypeAttributes.Public;

   // 構造函數(并非必須)

   CodeConstructor cc = new CodeConstructor();

   cc.Attributes = MemberAttributes.Public | MemberAttributes.Final;

   ctd.Members.Add(cc);

   // 成員函數MyMethod

   CodeMemberMethod cmm = new CodeMemberMethod();

   cmm.Name = "MyMethod";

   cmm.Attributes = MemberAttributes.Public | MemberAttributes.Final;

   cmm.Parameters.Add(

    new CodeParameterDeclarationExpression(

    typeof(string),"input"));

   cmm.Statements.Add(

    new CodeMethodInvokeExpression(

    new CodeSnippetExpression("Console"),"WriteLine",

    new CodeArgumentReferenceExpression("input")));

   ctd.Members.Add(cmm);

   cn.Types.Add(ctd);

   // 建立編譯單元

   CodeCompileUnit unit = new CodeCompileUnit();

   unit.Namespaces.Add(cn);

   return unit;

  }

  static Assembly ComplieCodeDomToAssembly(CodeCompileUnit compilationUnit,CodeDomProvider languageProvider)

  {

   // 預覽代碼

   Console.WriteLine("// 預覽代碼");

   StringBuilder sb = new StringBuilder();

   ICodeGenerator icg = languageProvider.CreateGenerator();

   icg.GenerateCodeFromCompileUnit(compilationUnit,new StringWriter(sb),null);

   Console.WriteLine(sb.ToString());

   ICodeCompiler complier = languageProvider.CreateCompiler();

   // 建立編譯參數

   CompilerParameters options = new CompilerParameters(new string[]{"MsCorLib.dll","System.dll"});

   // 在記憶體中建立Assembly

   options.GenerateInMemory = true;

   // 關閉調式資訊,提高性能

   options.IncludeDebugInformation = true;

   // 忽略警告

   options.TreatWarningsAsErrors = false;

   // 編譯并得到編譯結果

   CompilerResults results = complier.CompileAssemblyFromDom(options,compilationUnit);

   foreach(string str in results.Output)

   {

    Console.WriteLine(str);

   }

   if(results.NativeCompilerReturnValue != 0)

   {

    // 編譯失敗

    Console.WriteLine("!ERROR:");

    foreach(CompilerError error in results.Errors)

    {

     Console.WriteLine(error.ErrorText);

    }

    return null;

   }

   else

   {

    return results.CompiledAssembly;

   }

  }

  static void InvokeMethodsFromAssembly(Assembly assembly)

  {

   // 得到置于Assembly的class

   // 需要寫完整命名空間

   Type t = assembly.GetType("Sunmast.Sample.CodeDom.SunmastClass",true,true);

   // 調用構造函數建立對象

   Object obj = t.InvokeMember(null, BindingFlags.CreateInstance, null, null, null);

   // Object obj = Activator.CreateInstance(t); // 也可以這麼寫

   // 調用對象的方法(MyMethod)

   Console.WriteLine("Invoke Method /"MyMethod/": The END.");

   t.InvokeMember("MyMethod",BindingFlags.InvokeMethod, null, obj, new object[]{"The END."});

  }

 }

}