代码的动态编译并执行是一个NET平台提供给我们的很强大的工具用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑并通过一些额外的代码来扩展我们已有 的应用程序这在很大程度上给我们提供了另外一种扩展的方式(当然这并不能算是严格意义上的扩展但至少为我们提供了一种思路)
动态代码执行可以应用在诸如模板生成外加逻辑扩展等一些场合一个简单的例子为了网站那的响应速度HTML静态页面往往是我们最好的选择但基于数据驱动的网站往往又很难用静态页面实现那么将动态页面生成html的工作或许就是一个很好的应用场合另外对于一些模板的套用我们同样可以用它来做另外这本身也是插件编写的方式
最基本的动态编译
Net为我们提供了很强大的支持来实现这一切我们可以去做的基础主要应用的两个命名空间是SystemCodeDomCompiler和MicrosoftCSharp或MicrosoftVisualBasic另外还需要用到反射来动态执行你的代码动态编译并执行代码的原理其实在于将提供的源代码交予CSharpCodeProvider来执行编译(其实和CSC没什么两样)如果没有任何编译错误生成的IL代码会被编译成DLL存放于于内存并加载在某个应用程序域(默认为当前)内并通过反射的方式来调用其某个方法或者触发某个事件等之所以说它是插件编写的一种方式也正是因为与此我们可以通过预先定义好的借口来组织和扩展我们的程序并将其交还给主程序去触发一个基本的动态编译并执行代码的步骤包括
· 将要被编译和执行的代码读入并以字符串方式保存
· 声明CSharpCodeProvider对象实例
· 调用CSharpCodeProvider实例的CompileAssemblyFromSource方法编译
· 用反射生成被生成对象的实例(AssemblyCreateInstance)
· 调用其方法
以下代码片段包含了完整的编译和执行过程
//get the code to compile
string strSourceCode = thistxtSourceText;
// Create a new CSharpCodePrivoder instance
CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
// Sets the runtime compiling parameters by crating a new CompilerParameters instance
CompilerParameters objCompilerParameters = new CompilerParameters();
objCompilerParametersReferencedAssembliesAdd(Systemdll);
objCompilerParametersReferencedAssembliesAdd(SystemWindowsFormsdll);
objCompilerParametersGenerateInMemory = true;
// CompilerResults: Complile the code snippet by calling a method from the provider
CompilerResults cr = objCSharpCodePrivoderCompileAssemblyFromSource(objCompilerParameters strSourceCode);
if (crErrorsHasErrors)
{
string strErrorMsg = crErrorsCountToString() + Errors:;
for (int x = ; x < crErrorsCount; x++)
{
strErrorMsg = strErrorMsg + \r\nLine: +
crErrors[x]LineToString() + +
crErrors[x]ErrorText;
}
thistxtResultText = strErrorMsg;
MessageBoxShow(There were build erros please modify your code Compiling Error);
return;
}
// Invoke the method by using Reflection
Assembly objAssembly = crCompiledAssembly;
object objClass = objAssemblyCreateInstance(DynamiclyHelloWorld);
if (objClass == null)
{
thistxtResultText = Error: + Couldnt load class;
return;
}
object[] objCodeParms = new object[];
objCodeParms[] = Allan;
string strResult = (string)objClassGetType()InvokeMember(
GetTime BindingFlagsInvokeMethod null objClass objCodeParms);
thistxtResultText = strResult;
[] [] [] [] []