对于那些不熟悉脚本语言,同时又需要用到相关功能的人来说,C#动态编译不得不说是一个不错的选择。通过一段时间的研究,学会基本一些操作。总结出来做个小计。如有大虾经过,敬请赐教,留下高招!
首先,跟任何组件一样,引用命名空间是必不可少的。
然后通过自己程序文本将其封装为一个类,并且必须要声明该类中需要使用到的所有命名空间。提供可以供外部调用的public 函数,这样一个可以动态编译的程序集就创建好了。程序可以存为本地文件,也可以存放到数据库中。
接下来,是程序的的编译和调用。首先需要创建一个程序提供对象:
CodeDomProvider _CodeDomProvider = CodeDomProvider.CreateProvider("CSharp");
在.net 2.0以前的版本还需要创建一个调用它的接口,让后通过它来调用编译器:
ICodeCompiler _ICodeCompiler = _CodeDomProvider.CreateCompiler();
CompilerResults _CompilerResults = _ICodeCompiler.CompileAssemblyFromSource(_CompilerParameters, this.CreateCode());
但是在2.0之后如果还是采用这个办法就会提示函数已经过时了。因为在2.0以后的版本中,已经在程序提供对象里面实现了该函数,直接调用就可以了。当然你如果还是用1.1版本的方式来执行也是不会出错的。
CompilerResults _CompilerResults =_CodeDomProvider.CompileAssemblyFromSource(_CompilerParameters, this.CreateCode());
最后,通过采用放射的方式调用我们创建好的类里面的响应的函数就可以了。
(下附简单代码:)
using System.Reflection;
using System.Globalization;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
private string CreateCode()
{
StringBuilder sb = new StringBuilder();
//声明需要使用的命名空间。
sb.Append("using System;");
sb.Append("using System.Collections.Generic;");
sb.Append("using System.ComponentModel;");
sb.Append("using System.Data;");
sb.Append("using System.Drawing;");
sb.Append("using System.Text;");
sb.Append("using System.Windows.Forms;");
sb.Append(Environment.NewLine);
//将需要执行的功能this.code,字符串包装到一个类的函数里面。
sb.Append("namespace DynamicCodeGenerate");
sb.Append(Environment.NewLine);
sb.Append("{");
sb.Append(Environment.NewLine);
sb.Append(" public class HelloWorld");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.Append(" public void OutPut()");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.Append(this.code);
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
sb.Append("}");
//将所有声明的字符串返回给编译器使用。
string code = sb.ToString();
return code;
}
private void btnRun_Click(object sender, EventArgs e)
{
CodeDomProvider _CodeDomProvider = CodeDomProvider.CreateProvider("CSharp");
//提供对 C# 代码生成器和代码编译器的实例的访问
//CSharpCodeProvider _CSharpCodePrivoder = new CSharpCodeProvider();
//定义用于调用源代码编译的接口或使用指定编译器的 CodeDOM 树
//ICodeCompiler _ICodeCompiler = _CodeDomProvider.CreateCompiler(); //_CSharpCodePrivoder.CreateCompiler();
//表示用于调用编译器的参数,将所有需要使用的DLL和EXE文件添加打参数里面。
CompilerParameters _CompilerParameters = new CompilerParameters();
_CompilerParameters.ReferencedAssemblies.Add("System.dll");
_CompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
_CompilerParameters.ReferencedAssemblies.Add("CodeDom.exe");
_CompilerParameters.ReferencedAssemblies.Add("System.Data.dll");
_CompilerParameters.ReferencedAssemblies.Add("System.Drawing.dll");
_CompilerParameters.GenerateExecutable = false;
_CompilerParameters.GenerateInMemory = true;
//表示从编译器返回的编译结果
//CompilerResults _CompilerResults = _ICodeCompiler.CompileAssemblyFromSource(_CompilerParameters, this.CreateCode());
//在CodeDomProvider 类中已经实现了ICodeCompiler类中的CompileAssemblyFromSource()方法,直接调用就可以了!
CompilerResults _CompilerResults =_CodeDomProvider.CompileAssemblyFromSource(_CompilerParameters, this.CreateCode());
if (_CompilerResults.Errors.HasErrors)
{
string ErrorMessage="";
foreach (CompilerError err in _CompilerResults.Errors)
{
ErrorMessage += err.ErrorText;
}
MessageBox.Show(ErrorMessage);
}
else
{
// 通过反射,调用HelloWorld的实例
Assembly _Assembly = _CompilerResults.CompiledAssembly;
//CreateInstance()从此程序集中查找某个类型,然后使用系统激活器创建它的实例
object _HelloWorld = _Assembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
//发现方法的属性并提供对方法元数据的访问,获取OutPut()方法。
MethodInfo _MethodInfo = _HelloWorld.GetType().GetMethod("OutPut");
//执行objMI对象中的objHelloWorld对象中的函数。
_MethodInfo.Invoke(_HelloWorld, null);
}
}

浙公网安备 33010602011771号