CodeDom系列五--动态编译
2010-07-06 09:07 破狼 阅读(7386) 评论(5) 编辑 收藏 举报继上节我们把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编译:
45678910111213141516171819202122232425262728293031323334using
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
45678910111213141516(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
456789101112(option,unit);
}
public
CodeCompileUnit CodeDomHelloDemo()
{
//Mehtod
CodeEntryPointMethod method =
new
CodeEntryPointMethod();
//Console.WriteLine("Hello Word!");
CodeMethodInvokeExpression methodWrite =
new
CodeMethodInvokeExpression(
new
CodeTypeReferenceExpression(
typeof
(Console)),
"WriteLine"
,
456789101112131415161718192021222324new
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;
}
}
}
输出代码为:
456789101112131415161718192021222324252627282930313233343536373839404142//------------------------------------------------------------------------------
// <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文件:
![]()
4点击Demo5.exe运行视图:
今天就写到这里,睡觉了。CodeDom很简单,要了解的东西并不多。下面如果有机会就写几个示例Demo,
暂时考虑自动生成一些算法Code, 没有实际意义,或者是做个类编译器。 欢迎大家指正,共同学习共同进步。
作者:破 狼
出处:http://www.cnblogs.com/whitewolf/
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客、博客园--破狼和51CTO--破狼。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App