关于C#的动态类型与动态编译的简介,主要是一个Demo。

动态类型

动态类型的应用场景

  1. 可以减少强制转换(强制转换其实挺好的,让程序猿清楚地指定自己做了什么,不至于出错时不知所措)
  2. 简化反射的写法。
  3. 与动态语言交互。
// Install-Package IronPython // 需要安装此 Nuget包
// 引入动态类型之后
// 可以在C#语言中与动态语言进行交互
// 下面演示在C#中使用动态语言Python ScriptEngine 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;
}

详细下介绍可以看这里:

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#的一个动态编译引擎。

简介看这里:

如果用原生的动态编译,每次都要生成一个程序集,然后通过反射的方式去调用,过于麻烦。

如果只是想动态编译一句代码,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;
}

C# 动态类型与动态编译简介的更多相关文章

  1. OC 动态类型,动态绑定,动态加载

    OC 动态类型,动态绑定,动态加载 Objective-C具有相当多的动态特性,基本的,也是经常被提到和用到的有 动态类型(Dynamic typing) 动态绑定(Dynamic binding) ...

  2. 《精通C#》第十六章-动态类型和动态语言运行时-第一节至第四节

    在.Net4.0中引入了一个关键字dynamic,这是一个动态类型关键字.Net中还有一个关键字是var,这是一个隐式类型,可以定义本地变量,此时var所代表的实际的数据类型有编译器在初次分配时决定, ...

  3. C# 4.0中的动态类型和动态编程

    # 4.0的主题就是动态编程(Dynamic Programming).虽然C#仍然是一种静态语言,但是对象的意义开始变得越来越“动态”.它们的结构和行为无法通过静态类型来捕获,或者至少编译器在编译程 ...

  4. 动态类型识别&动态创建

    以下大部分内容摘自<windows程序设计 第2版> 王艳平 张铮 编著 动态类型识别:在程序运行过程中,辨别对象是否属于特定类的技术. 应用举例:函数辨别参数类型.需要针对对象的类编写特 ...

  5. C#学习笔记(十一):动态类型

    C#是一门静态类型的语言,但是在C#4.0时微软引入了动态类型的概念. dynamic 关键字dynamic用来定义动态对象,我们来看一下动态类型的一些特性. 调用不同类的相同方法 我们有两个或多个不 ...

  6. C# 匿名对象(匿名类型)、var、动态类型 dynamic

    本文是要写的下篇<C#反射及优化用法>的前奏,不能算是下一篇文章的基础的基础吧,有兴趣的朋友可以关注一下. 随着C#的发展,该语音内容不断丰富,开发变得更加方便快捷,C# 的锋利尽显无疑. ...

  7. C# 匿名对象(匿名类型)、var、动态类型 dynamic——实用之:过滤类属性、字段实用dynamic

    例子 返回一个LIst<oject>类型 而oject含有 30个字段 而我只需要两个字段.这里实用dynamic 和 linq. 上代码: 注意select new {} 为匿名类型,这 ...

  8. 面向对象的JavaScript --- 动态类型语言

    面向对象的JavaScript --- 动态类型语言 动态类型语言与面向接口编程 JavaScript 没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承. Jav ...

  9. 静态类型&动态类型

    何时使用:使用存在继承关系的类型时,必须将一个变量或其他表达式的静态类型与该表达式表示对象的动态类型区分开来 静态类型:表达式的静态类型在编译时总是已知的,它是变量声明时的类型或表达式生成的类型 动态 ...

随机推荐

  1. JS替换地址栏参数值

    首先,页面引入JS代码片段(整体复制粘贴即可): var Query=function(a){"use strict";var b=function(a){var b=[],c,d ...

  2. 【BZOJ】2208 [Jsoi2010]连通数

    [题意]给定n个点的有向图,求可达点对数(互相可达算两对,含自身).n<=2000. [算法]强连通分量(tarjan)+拓扑排序+状态压缩(bitset) [题解]这题可以说非常经典了. 1. ...

  3. 训练赛第三场A题 zoj 559

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2559 解题报告:比赛的时候的想法是可以确定至少有两对相切的圆,所 ...

  4. Macaca(一) - 环境配置

    Macaca是阿里提供的一套自动化测试框架,目前已开源. 花了两三个小时研究了一下Macaca的实现原理.因为很好奇它与appium.selenium有啥区别. 实现原理本质上与selenium的we ...

  5. connect by和strart with子句

    --使用connect by和strart with子句 SELECT [level],column,expression, ... FROM table [WHERE where_clause] [ ...

  6. 【bzoj题解】1001 狼抓兔子

    题目描述 现在小朋友们最喜欢"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:   ...

  7. Docker技术这些应用场景【转】

    场景一:节省项目环境部署时间 1.单项目打包 每次部署项目到测试.生产等环境,都要部署一大堆依赖的软件.工具,而且部署期间出现问题几率很大,不经意就花费了很长时间. Docker主要理念就是环境打包部 ...

  8. avalonJS-源码阅读(二)

    上一篇文章讲述的avalon刷页面所用到的几个函数.这篇则是主要讲avalon对刷DOM刷出来的avalon自定义属性如何处理的. 目录[-] avalon页面处理(2) 数据结构 解析avalon标 ...

  9. HDU 6196 happy happy happy 爆搜加剪枝

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6196 题意:给你长度为n的序列,爸爸和儿子玩一个游戏,儿子先手,儿子每次都选择最左边与最右边最大的那个 ...

  10. 二十一、springboot之定制URL匹配规则(项目中遇到的问题:get方式传参,带有小数点,被忽略)

    一.问题描述: get方式传参,在传送价格,积分时(带有小数点),debug后台微服务接受到的参数,却不带小数点,如:price是0.55,后台接受后却是0 二.解决 在WebConfiguratio ...