动态生成与编译(八)----动态编译

 

上次把实实在在的源代码生成了,不再是抽象的东西了,现在要用程序动态的来编译上次的东西。

System.CodeDOM.Compiler中的三个接口都是从CodeDomProvider得到的(上次强调过了),这次用到的接口是ICodeCompiler,所以先:

                CSharpCodeProvider provider = new CSharpCodeProvider();

           ICodeCompiler compiler = provider.CreateCompiler();

这个接口的方法全是CompileAssemblyFrom*这种形式的,分别是*FromDom**FromFile**FromSource*,从此可以看出动态编译不只是从文件来编译,它可以直接从生成的CodeDOM直接编译,也可以从包含源代码的字符串编译(FromSource这个)。而且它可以一起编译好几个的,如CompileAssemblyFromDomBatch,当然也有*FileBatch之类的。

 

编译与生成写法很象的,得到接口后就是一个*From*的方法也就好了。以CompileAssemblyFromFile为例:

CompilerResults CompileAssemblyFromFile( 
       
   CompilerParameters options,
   string fileName

);

也是一个参数作为源,这里就是fileName了;目的地,生成代码的时候是有个TextWrite类型的参数作为去向,而这里就是返回一个CompilerResults类型表示编译后的结果;在生成的时候有个CodeGeneratorOptions,这里也有一个options,只是类型不同而已,这里是CompileParameters,而编译的奥秘当然也就在这个CompileParameters里了。

 

上面这个CompileParameters里设置的属性是很丰富,不过我没怎么玩过编译器,有些也不知道怎么跟编译时的哪个选项相对应。

string CompilerOptions第一个就搁浅了,options这个概括太笼统,它说是附加的命令行参数,我不知道它是应该对应编译器选项里的哪些,难道是只要下面没有涉及过的选项都用这个来设吗?

Evidence Evidence这个是证据,安全方面的东西,很少涉及,不太懂。

bool GenerateExecutable是不是生成可执行文件,默认下是false,就是生成DLL文件。

bool GenerateInMemory编译时在内存输出,默认情况下是不是的,都是输出到硬盘,大家大多也是这么干。要输出到内存设为true就是了。

bool IncludeDebugInformation要不要生成调试信息,这没什么好说的。

string MainClass主类的名称。

string OutputAssembly输出程序集名称。

StringCollection ReferencedAssemblies引用程序集的名称。

TempFileCollection TempFiles临时文件。

bool TreatWarningsAsErrors是否将警告视为错误。

IntPtr UserToken创建编译器进程时的用户标记,这个不是很懂。

int WarningLevel中止编译的警告等级。

string Win32Resource要连接到已编译程序集中的Win32资源文件。

 

可设置的属性是比较的多,但比起编译器的选项来好象还是有点小巫见大巫。看来很多东西是在刚开始的那个CompileOptions设置的。

 

一般情况下很多属性都保持默认就是了,直接在构造函数里把最需要的东西设置出来就是了如下:

                //编译参数

                CompilerParameters cp = new CompilerParameters(new string[] {"System.dll"},

                     filepath.Substring(0,filepath.LastIndexOf(".") + 1) + "exe",false);

           cp.GenerateExecutable = true;//生成EXE,不是DLL

上面的这个构造函数是全的构造函数了(再要设属性就只能new后再设置了)。第一个参数就是引用的程序集,第二个是输出文件名,第三个是要不要调试信息。

 

再来一句:

CompilerResults cr = compiler.CompileAssemblyFromFile(cp,filepath);

编译结束。

 

用那个文件或CodeDOM或一堆源代码的字符串编译成功了没有,可以从返回的那个CompilerResults来查看。这个CompileResults里也有好多东西可以查看的。

CompiledAssembly 属性指示编译的程序集。

Evidence 属性指示程序集的安全证据。

PathToAssembly 属性指示编译的程序集的路径(如果不是只在内存中生成编译的程序集)。

Errors 属性指示任何编译器错误和警告。

Output 属性包含编译器输出消息。

NativeCompilerReturnValue 属性指示编译器返回的结果代码值。

TempFiles 属性指示编译和链接过程中生成的临时文件。

 

这些都很简单的。至此编译的任务结束。

 

动态生成与编译的基本的东西没了,主要的麻烦在生成CodeDOM上,难倒不难,就是长长的代码麻烦一点。生成源代码与动态编译基本没有什么亮点。

不过下面还有个ICodeParser没有实现的,这里好象有点难度的,有点字符串分析的味道。前两天在CodeProject找到了一个,不过那个是两年前的代码,那时的Nunit跟现在的好象都不一样,我把它的单元测试部分拿掉才能编译通过。现在要分析一下它那个东西,不知有什么收获。

你可能感兴趣的:(动态编译)