C# 动态编译简介

C# 动态类型与动态编译简介
动态类型
动态编译
CSScript
关于C#的动态类型与动态编译的简介,主要是一个Demo。
动态类型
关键字:dynamic
这里有详细的介绍:[C#基础知识系列]专题十七:深入理解动态类型
动态类型的应用场景
可以减少强制转换(强制转换其实挺好的,让程序猿清楚地指定自己做了什么,不至于出错时不知所措)
简化反射的写法。
与动态语言交互。
// Install-Package IronPython // 需要安装此 Nuget包// 引入动态类型之后// 可以在C#语言中与动态语言进行交互// 下面演示在C#中使用动态语言PythonScriptEngine engine = Python.CreateEngine();// 调用Python语言的print函数来输出engine.Execute("print 'Hello world'");// 调用python求解汉罗塔问题engine.Execute(PythonCode1());// 调用python进行计算,返回 dynamic 类型dynamic result = engine.Execute("123+456");public static string PythonCode1(){string code = "count=0\n" +"def move(n,A,B,C):\n" +" global count\n" +" if(n==1):\n" +" print(A+\"->\"+C)\n" +" count = count + 1\n" +" return\n" +" move(n - 1, A, C, B)\n" +" move(1, A, B, C)\n" +" move(n - 1, B, A, C)\n" +" return\n" +"move(5,\"A\",\"B\",\"C\")";return code;}
动态编译
javascript 和 matlab 等脚本语言会有 eval 这个函数,可以将一些动态生成的字符串作为代码执行,某些情况下很实用。
C#同样支持动态编译。
最主要的两个类:
CodeDomProvider 和 CompilerParameters
前者相当于编译器,后者相当于编译器参数。
public static void Test1(){CodeDomProvider compiler = new CSharpCodeProvider(); //编译器CompilerParameters comPara = new CompilerParameters(); //编译器参数comPara.GenerateExecutable = true; // 生成exe文件comPara.GenerateInMemory = false; // 是否在内存在输出comPara.OutputAssembly = "SimpleCompile.exe"; // 输出文件compiler.CompileAssemblyFromSource(comPara, GetCode1());// 在当前目录生成 SimpleCompile.exe ,可直接运行}public static string GetCode1(){string code = @"using System;class Test{static void Main(){Console.WriteLine(""Hello world"");Console.ReadLine();}}";return code;}
详细下介绍可以看这里:
C# 动态编译
.NET Framework 中的动态编程
public static void Test2(){CodeDomProvider compiler = new CSharpCodeProvider(); //编译器CompilerParameters comPara = new CompilerParameters(); //编译器参数comPara.GenerateExecutable = false;comPara.GenerateInMemory = true;// GetCode2() 见文末CompilerResults compilerResults = compiler.CompileAssemblyFromSource(comPara, GetCode2());if (compilerResults.Errors.HasErrors){Console.WriteLine("编译错误");foreach (CompilerError err in compilerResults.Errors){Console.WriteLine(err.ErrorText);}return;}// 通过反射,调用HelloWorld的实例Assembly objAssembly = compilerResults.CompiledAssembly;object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");MethodInfo objMi = objHelloWorld?.GetType().GetMethod("OutPut");var result = objMi?.Invoke(objHelloWorld, null);Console.WriteLine(result);// 动态类型调用// 可以看到,动态调用比反射调用写法简介不少dynamic dynObj = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");var result2 = dynObj?.OutPut();Console.WriteLine(result2);}
CSScript
CSScript是C#的一个动态编译引擎。
简介看这里:
C#动态编译引擎-CS-Script
CSScript.Net脚本概述
Nuget
Github
如果用原生的动态编译,每次都要生成一个程序集,然后通过反射的方式去调用,过于麻烦。
如果只是想动态编译一句代码,CSScript提供了一种特别方便的写法。
var sqr = CSScript.Evaluator.CreateDelegate(@"int Sqr(int a){return a * a;}");var r = sqr(3); // 计算3的平方
使用 CS-Script 需要安装相关Nuget包 (会安装很多东西,依赖项很多)
Install-Package CS-Script
Scripting.evaluator.cs
Scripting.Extensions.cs
Scripting.native.cs
这三个文件是 Nuget 安装 CS-Script 之后自动载入的,里面有很多实用的例子~
有了CSScript,对原有的动态编译的调用也变得简单。
public static void Test1(){// 得到 Assembly,反射调用Assembly ass = CSScript.LoadCode(GetCode2()); // GetCode2()见文末AsmHelper assAsmHelper = new AsmHelper(ass);object obj = assAsmHelper.CreateObject("DynamicCodeGenerate.HelloWorld");var method = assAsmHelper.GetMethod(obj, "OutPut");object result = method.Invoke();// 动态调用dynamic obj2 = CSScript.Evaluator.LoadCode(GetCode2());dynamic result2 = obj2.OutPut();}
关于CSScript的性能问题,可以参看这里:C#脚本引擎 CS-Script 之(二)——性能评测
public static string GetCode2(){StringBuilder sb = new StringBuilder();sb.Append("using System;");sb.Append(Environment.NewLine);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 string OutPut()");sb.Append(Environment.NewLine);sb.Append(" {");sb.Append(Environment.NewLine);sb.Append(" return \"Hello world!\";");sb.Append(Environment.NewLine);sb.Append(" }");sb.Append(Environment.NewLine);sb.Append(" }");sb.Append(Environment.NewLine);sb.Append("}");string code = sb.ToString();return code;}
.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
【.NET Core微服务实战-统一身份认证】开篇及目录索引
Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南)
.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
用abp vNext快速开发Quartz.NET定时任务管理界面
