C#中动态编译应用程序

转载 2006年06月12日 15:05:00

大家都知道,在ASP.NET中利用CodeBehind技术编写好的文件必须先通过编译,然后才能被执行。我们一般是在VS.NET中或者命令行下进行编译,那么现在的问题就是在程序中进行编译,也就是自己通过做好的规则动态生成一些程序源文件、然后对其进行编译。查看.Net Framework中提供的类库,发现了Microsoft.Csharp这个命名空间,其中有一个类Compiler。要调用这个类库必须先在引用中添加D:/WINNT/Microsoft.NET/Framework/v1.0.3705/cscompmgd.dll这个文件,这是我机器上的路径,各位根据自己机器所在路径设置吧。

仔细研究Compiler这个类:不需要初始化,直接可使用Compile方法,其中包含了5个参数。

string[] sourceTexts 源代码数组 其中每一个值包含一个文件中的源码

string[] sourceTextNames 源文件名数组 其中每一个值包含了一个文件名和上面的源代码数组中的值一一对应。

string target 输出的文件名

string[] imports 引用类库数组 也就是我们在VS.net中引用的那些类库的文件路径,一般都是dll文件,其中一个值表示一个引用文件。

IDictionary options 参数设置,实际上这也是一个数组,可以包含多个参数,具体的参数我在下面的部分会讲到。

 

实际这个Compile这个方法要求我们输入这些条件:

1、源代码——这个是必须的,没有源代码没法编译,那么源代码要求我们从程序文件中读取出来。

2、源文件的名称,和读取出的源代码一一对应。

3、编译输出的文件名,也可不填

4、引用的类库文件,如System.dll,System.data.dll这些都是经常会用到的。

5、其他参数设置

 

第一步:创建一个类及调用方法

首先我们创建一个Class

using System;

using System.IO;

using System.Text;

using Microsoft.CSharp;

 

namespace MyTest

{

private String[] filelist; //文件列表

private String[] cscode; //源代码

private String[] filename; //文件名

private String[] import; //引用类库

public class MyComplier()

{

 

//这里我做了一个简单的方法,要求用户输入两个参数,一个是文件夹的绝对路径

另外一个是输出的文件路径

public CompilerError[] MyCompile(String realpath,String output)

{

//……………………

}

 

}

}

那么下面我们会一步步来讲解如何实现这个方法。

 

第二步:读取程序文件列表

 

由于使用CodeBehind,那么实际上要编译的也就是扩展名为CS的文件。首先读取文件列表,制作一个方法用来读取目录下的文件路径:通过用户输入的绝对路径对文件进行整理搜索。

 

public String[] GetFileList(String realpath)//输入绝对路径

{

return System.IO.Directory.GetFiles(realpath,”*.cs”);//输入搜索条件

}

 

本方法将要编译的真实目录传递进入,然后返回目录下扩展名为CS的文件路径列表。那么读取文件的列表将会为文件中代码的获取及文件名的获取做准备。

 

第三步:读取程序文件内容

//这里我们调用了第二步建立的方法来获取文件列表

filelist= GetFileList(realpath); //获取文件路径列表

//根据文件的数量创建数组

cscode=new String[filelist.Length]; //建立源代码数组

String[] filename=new String[filelist.Length];//建立源文件名数组

//通过循环获取每个文件的信息每增加到对应的数组中

For (int I=0;I

{

String filepath= filelist. GetValue(i).ToString();//获取单个文件路径

cscode[I]= ReadTxtFile(filepath, Encoding.GetEncoding("GB2312"));//读取源文件中的代码、这里的编码为GB2312,也可设置为其他,这里调用的是我们下面创建的一个方法

filename[I]= System.IO.Path.GetFileName(filepath);//获取文件名

}

 

//读取文本文件内容

public String ReadTxtFile(String path,Encoding encode)

{

String str="";

try

{

if (File.Exists(path))

{

StreamReader sr=new StreamReader(path,encode);

str=sr.ReadToEnd();

sr.Close();

}

}

catch(IOException ex)

{Console.Write(ex.ToString());}

return str;

}

经过第二步之后我们已经满足了Compile方法所需的两个参数了,那么接下来将是对文件的输出及引用的一些配置。

 

第四步:配置输出文件名及路径

此处可根据你的需要,设置文件和路径,例如:E:/test/bin/test.dll String output=” E://test//bin//test.dll”;

这里我们根据用户输入的路径进行操作。

 

第五步:配置引用的类库文件

那么只要是你在程序引用到的类库,在此处都必须加入到数组中。

import=new String[10];//定义一个数组,数组长度根据你所需要引用的文件数量决定

import[0]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//System.dll";

import[1]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//IEHost.dll";

import[2]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//System.Data.dll";

import[3]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//System.Drawing.dll";

import[4]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//System.Web.dll";

import[5]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//System.Xml.dll";

import[6]="D://WINNT//Microsoft.NET//Framework//v1.0.3705//cscompmgd.dll";

上面的是我们经常用到的一些类库,除此之外,你自己编写的一些类库,如果也被引用到了,那么也必须增加到数组中。

 

第六步:进行属性参数配置

这里系统提供给了我们一个接口:Idictionary,这个接口可使用以下几个类来实现。

 

ListDictionary 使用单链接列表实现 IDictionary。建议用于通常包含 10 个或 10 个以下项的集合。

HybridDictionary在集合较小时,使用 ListDictionary 来实现 IDictionary,然后当集合变大时,切换到 Hashtable。

还有其他一些,我感觉用不上,这里就不讲了。那么,具体来看看:

 

System.Collections.IDictionary configs=new System.Collections.Specialized.ListDictionary();//实现这个接口

configs.Add("target","library"); //配置输出文件类型为库文件,这个参数是必须的

其中”target”为文件的格式属性,”library”为属性的值。

 

其他属性有:

addmodule 导入元数据 要包含在此程序集内的模块列表。模块名必须用竖线或管道字符分隔。值的类型必须是 String。

baseaddress 库的基址。值的类型必须是 Uint32

bugreport 产生错误报告文件。值的类型必须是 String。

checked 检查整数算法 设置默认表达式计算为选中(或未选中)。值的类型必须是 Boolean。

Debug发出调试信息 值的类型必须是 Boolean。不能指定“全部”或“pdbonly”。

Lib 指定程序集引用位置 查找模块和引用的程序集时要搜索的附加路径。值的类型必须是 String。

Unsafe启用不安全模式 允许不安全构造。值的类型必须是 Boolean

win32icon自动生成的 Win32 资源的 Win32 图标。值的类型必须是String

这里讲出主要的一些参数,还有一些由于用得比较少,那么就不一一列出了。

 

第七步:程序编译

CompilerError[] ce= Compiler.Compile(cscode,filename, output,import, configs);

那么实际上我们最后的编译也就是调用这个方法,此方法将会返回一个包含出错信息的数组。其中记录了编译过程中的出错信息,如果有错误信息返回,则编译无法通过。

 

最后我们将第一步中的方法整合:

 

public CompilerError[] MyCompile(String realpath,String output)

{

//……………………

通过上面的方法获取到参数,最后执行编译。

CompilerError[] ce= Compiler.Compile(cscode,filename, output,import, configs);

return ce;

}

 

到这里,基本上整个编译过程就完成了,大家可以在Aspx页面中调用或者在其他的类中调用,编译出来的效果和VS.net比起来一点不差,而且速度也非常快。大家甚至可以构建一个基于Web的简易的集成开发环境,当然这是后话了。

让C#语言充当自身脚本!——.NET中的动态编译

代码的动态编译并执行是一个.NET平台提供给我们的很强大的工具用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码来扩展我们已有 的应用程序。这在很大程度上给我们提供了另外...
  • clb929
  • clb929
  • 2016年05月12日 16:57
  • 5923

动态编译C#代码

项目开发中,有时候会使用到动态生成代码,然后根据动态生成的代码再执行相应的操作,C#提供了动态代码的编译,利用这个特性可以实现动态生成代码,然后执行代码。 直接上代码,c#版本[MenuI...
  • suifcd
  • suifcd
  • 2016年05月11日 19:46
  • 1216

【经典实例】利用C#反射动态编译代码,创建类的实例,并调用其成员

关键是以下内容有一些需要学习的地方。GenerateCode()函数动态生成编译代码,还有动态调用类的函数名。反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了《...
  • wonsoft
  • wonsoft
  • 2010年01月16日 01:26
  • 4044

C#动态编译、执行代码

原文地址:http://blog.csdn.net/21aspnet/article/details/3281147
  • clb929
  • clb929
  • 2016年05月11日 06:43
  • 1163

动态编译执行C#代码

所谓动态代码执行,和脚本引擎有点类似。就是程序执行期从字符串或者文本文件中读取一段 C# 代码,在内存中动态编译成程序集,并创建相关类型实例执行相关方法。具体的实现可参考下面的代码。如需要生成程序集文...
  • daonidedie
  • daonidedie
  • 2008年03月07日 15:10
  • 537

C# 动态编译执行器,Excuter.exe

C# 动态编译执行器,Excuter.exe。动态编译执行器,可执行任意逻辑,实现源码与工具的分离。...
  • scimence
  • scimence
  • 2017年08月09日 12:32
  • 257

C#动态编译,实现按钮功能动态配置

现在对做的系统要求要越来越灵活,功能配置越来越方便,牺牲一小部分的效率,而换取系统的灵活性,对于维护、功能扩展升级等工作提供了很大的方便。 前两天,一个项目要求界面上的按钮都是可以配置的,位...
  • xiaoxian8023
  • xiaoxian8023
  • 2013年01月09日 23:36
  • 7852

c#动态编译,自己做了个c#脚本管理框架,可以作为其他应用的插件使用。增强程序的拓展性

一直在CSDN汲取养分,学到了很多东西,抽个时间也反哺一下。 c#动态编译 1、初衷        最近在做一个物联网服务器的cs版,由于业务的可变性太大,每次去更新正在运行的服务器不仅会带来一...
  • u013456701
  • u013456701
  • 2017年05月25日 21:01
  • 1019

C#发现之旅:于动态编译的VB.NET脚本引擎

脚本的原理   脚本,也可称为宏,是一种应用系统二次开发的技术,它能在应用系统提供的一个容器环境中运行某种编程语言,这种编程语言代码调用应用系统提供的编程接口,使得应用系统暂时“灵魂附体”,无需...
  • action20
  • action20
  • 2014年01月25日 21:37
  • 1783

c#动态编译,动态生成程序集

首先引入命名空间 1using System.CodeDom.Compiler;其次我们要了解CSharpCodeProvider这个类是用于动态编译c#程序集,它继承了ICodeCompi...
  • kllxyu
  • kllxyu
  • 2013年12月27日 17:44
  • 1369
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#中动态编译应用程序
举报原因:
原因补充:

(最多只允许输入30个字)