写这篇笔记的理由是因为上篇g提高的工具LINQPad见
想用LINQ思考吗?扔掉SQL查询分析器Come on LINQPad!
该工具的实现就有执行动态代码的应用
应用场景
还没想出来会用到哪里动态的代码由谁来写?普通用户我想有一定的困难
特别是有了像 IronPython 这样更容易使用的动态嵌入脚本
) 像 LINQPad 这样的辅助开发工具
) 实现脚本引擎?
) 探讨
主要使用命名空间 MicrosoftCSharp 编译C#代码然后使用 CodeDom 和 反射调用我这里写了一个测试工具看代码
using System; using SystemCollectionsGeneric; using SystemComponentModel; using SystemDrawing; using SystemWindowsForms; using SystemCodeDomCompiler; using MicrosoftCSharp; // 用于编译C#代码 using SystemReflection; // 用于反射调用 namespace CodeDomLearn { public partial class Form : Form { public Form() { InitializeComponent(); } private void button_Click(object sender EventArgs e) { CodeCompilerCompile(new string[] { } textBoxText ); listBoxItemsClear(); foreach (string s in CodeCompilerErrorMessage) { listBoxItemsAdd(s); } listBoxItemsAdd(CodeCompilerMessage); } } static class CodeCompiler { static public string Message; static public List<string> ErrorMessage = new List<string>(); public static bool Compile(string[] references string source string outputfile) { // 编译参数 CompilerParameters param = new CompilerParameters(references outputfile true); paramTreatWarningsAsErrors = false; paramGenerateExecutable = false; paramIncludeDebugInformation = true; // 编译 CSharpCodeProvider provider = new CSharpCodeProvider(); CompilerResults result = providerCompileAssemblyFromSource(param new string[] { source }); Message = ; ErrorMessageClear(); if (!resultErrorsHasErrors) { // 反射调用 Type t = resultCompiledAssemblyGetType(MyClass); if (t != null) { object o = resultCompiledAssemblyCreateInstance(MyClass); Message = (string)tInvokeMember(GetResult BindingFlagsInstance | BindingFlagsInvokeMethod | BindingFlagsPublic null o null); } return true; } foreach (CompilerError error in resultErrors) { // 列出编译错误 if (errorIsWarning) continue; ErrorMessageAdd(Error( + errorErrorNumber + ) + errorErrorText + \t\tLine: + errorLineToString() + Column:+errorColumnToString()); } return false; } } }
作为演示例子简单的规定类名必须是MyClass必须有一个方法返回 string 类型的 GetResult 方法这是执行效果图