CodeDom系列五--动态编译

  1. 云栖社区>
  2. 博客列表>
  3. 正文

CodeDom系列五--动态编译

ghost丶桃子 2016-05-23 16:23:38 浏览533 评论0

摘要:         继上节我们把Code 表达式编译成为了Code代码,有时我们只想动态编译程序集,在内存中或者是 硬盘上调用,这就是CodeDom的动态编译。微软在CodeDom中提供了动态编译程序,这是ICodeComp iler的用武之地了,它定义用于调用源代码编译的接口或使用指定编译器的 CodeDOM 树。

        继上节我们把Code 表达式编译成为了Code代码,有时我们只想动态编译程序集,在内存中或者是

硬盘上调用,这就是CodeDom的动态编译。微软在CodeDom中提供了动态编译程序,这是ICodeComp

iler的用武之地了,它定义用于调用源代码编译的接口或使用指定编译器的 CodeDOM 树。可以从CodeDomProvider生成引用对象:CodeDomProvider.CreateProvider("").CreateCompiler();

      在ICodeCompiler中为我们提供了程序集编译的方法有: 
            CompileAssemblyFromDom :使用指定的编译器设置从指定的 CodeCompileUnit 所包含的 System.CodeDom 树中编译程序集。 
            CompileAssemblyFromDomBatch:基于包含在 CodeCompileUnit 对象的指定数组中的 System.CodeDom 树,使用指定的编译器设置编译程序集。  
            CompileAssemblyFromFile:从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。  
            CompileAssemblyFromFileBatch:从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。  
            CompileAssemblyFromSource: 从包含源代码的指定字符串,使用指定的编译器设置编译程序集。 
            CompileAssemblyFromSourceBatch:从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。

在我们的CodeDomProvider也提供了CompileAssemblyFromDom、CompileAssemblyFromFile、CompileAssemblyFromSource。

       在他们的编译时候都有一个变异参数CompilerParameters,提供了编译时参数选项: 
CompilerOptions:获取或设置调用编译器时使用的可选附加命令行参数字符串。 
EmbeddedResources:获取要在编译程序集输出时包含的 .NET Framework 资源文件。 
Evidence:指定一个证据对象,该对象表示要授予已编译的程序集的安全策略权限。 
GenerateExecutable:获取或设置一个值,该值指示是否生成可执行文件。 
GenerateInMemory:获取或设置一个值,该值指示是否在内存中生成输出。 
IncludeDebugInformation:获取或设置一个值,该值指示是否在已编译的可执行文件中包含调试信息。 
LinkedResources:获取当前源中引用的 .NET Framework 资源文件。 
MainClass:获取或设置主类的名称。 
OutputAssembly:获取或设置输出程序集的名称。 
ReferencedAssemblies:获取当前项目所引用的程序集。 
TempFiles:获取或设置包含临时文件的集合. 
TreatWarningsAsErrors:获取或设置一个值,该值指示是否将警告视为错误。 
UserToken:获取或设置在创建编译器进程时使用的用户标记。 
WarningLevel:获取或设置使编译器中止编译的警告级别。 
Win32Resource:获取或设置要链接到已编译程序集中的 Win32 资源文件的文件名。

他们的结果返回编译结果CompilerResults,提供了编译结果信息: 
CompiledAssembly:获取或设置已编译的程序集。 
Errors:获取编译器错误和警告的集合。 
Evidence:指示证据对象,该对象表示编译的程序集的安全策略权限。 
NativeCompilerReturnValue:获取或设置编译器的返回值。 
Output:获取编译器输出消息。 
PathToAssembly:获取或设置已编译程序集的路径。 
TempFiles:获取或设置要使用的临时文件集合。

下面我们就来的Demo:实现简单的HelloWord编译:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
namespace CodeDomDemo4
{
class Program
{
static void Main(string[] args)
{
Program pro = new Program();
CodeCompileUnit unit= pro.CodeDomHelloDemo();
Console.WriteLine(pro.GenerateCode(unit, "c#"));
Console.WriteLine(pro.GenerateCode(unit, "vb"));
CompilerResults result=  pro.CompilerCode(unit, "c#");
if (result.Errors != null)
{
foreach (var item in result.Errors)
{
Console.WriteLine(item);
}
}
Console.Read();
}
public string GenerateCode(CodeCompileUnit unit, string language)
{
StringBuilder sb = new StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter();
CodeDomProvider.CreateProvider(language).GenerateCodeFromCompileUnit
(unit, sw,null);
sw.Close();
return sw.ToString();
}
public CompilerResults CompilerCode(CodeCompileUnit unit, string language)
{
CompilerParameters option = new CompilerParameters();
option.GenerateExecutable = true;
option.GenerateInMemory = false;
option.IncludeDebugInformation = true;
option.ReferencedAssemblies.Add("System.dll");
option.OutputAssembly = "Demo5.exe";
return CodeDomProvider.CreateProvider(language).CompileAssemblyFromDom
(option,unit);
}
public CodeCompileUnit  CodeDomHelloDemo()
{
//Mehtod
CodeEntryPointMethod method = new CodeEntryPointMethod();
//Console.WriteLine("Hello Word!");
CodeMethodInvokeExpression methodWrite = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression(typeof(Console)), "WriteLine", 
new CodePrimitiveExpression("Hello Word!"));
//Console.Read();
CodeMethodInvokeExpression methodread = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression(typeof(Console)), "Read");
method.Statements.Add(methodWrite);
method.Statements.Add( methodread);
//class Hello
CodeTypeDeclaration hello = new CodeTypeDeclaration("Hello");
hello.Attributes = MemberAttributes.Public;
hello.Members.Add(method);
//namespace Demo5
CodeNamespace nspace = new CodeNamespace("Demo5");
nspace.Imports.Add(new CodeNamespaceImport("System"));
nspace.Types.Add(hello);
//CodeCompileUnit
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nspace);
return unit;
}
}
}

输出代码为:

//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:2.0.50727.4927
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Demo5 {
using System;
public class Hello {
public static void Main() {
System.Console.WriteLine("Hello Word!");
System.Console.Read();
}
}
}
'------------------------------------------------------------------------------
' <auto-generated>
'     此代码由工具生成。
'     运行时版本:2.0.50727.4927
'
'     对此文件的更改可能会导致不正确的行为,并且如果
'     重新生成代码,这些更改将会丢失。
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict Off
Option Explicit On
Imports System
Namespace Demo5
Public Class Hello
Public Shared Sub Main()
System.Console.WriteLine("Hello Word!")
System.Console.Read
End Sub
End Class
End Namespace
在bin/debug下有生成Demo5.exe和Demo5.pdb文件:
image
点击Demo5.exe运行视图:
image
今天就写到这里,睡觉了。CodeDom很简单,要了解的东西并不多。下面如果有机会就写几个示例Demo,
暂时考虑自动生成一些算法Code, 没有实际意义,或者是做个类编译器。 欢迎大家指正,共同学习共同进步。


作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2010/07/06/1771868.html


【云栖快讯】你想见的Java技术专家都在这了,向大佬提问,有问题必答  详情请点击

网友评论

ghost丶桃子
文章2301篇 | 关注242
关注
兼容Jenkins标准,可提供快速可靠的持续集成与持续交付服务。基于容器技术和阿里云基础服务... 查看详情
独立的公网IP资源,可以绑定到阿里云专有网络VPC类型的ECS、NAT网关、私网负载均衡SL... 查看详情
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效... 查看详情
阿里云总监课正式启航

阿里云总监课正式启航