关于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#同样支持动态编译。

最主要的两个类:

CodeDomProviderCompilerParameters

前者相当于编译器,后者相当于编译器参数。

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. 多角度看.NET面试题

    1.ASP.NET中的身份验证有那些?你当前项目采用什么方式验证请解释        身份验证是从用户获取名称和密码等标识凭证并根据某些机构验证这些凭据的过程.如果凭据有效,则提交该凭据的实体被视为通 ...

  2. UNIX环境高级编程 第13章 守护进程

    守护进程daemon是一种生存周期很长的进程.它们通常在系统引导时启动,在系统关闭时终止.守护进程是没有终端的,它们一直在后台运行. 守护进程的特征 在Linux系统中,可以通过命令 ps -efj ...

  3. 富文本存储型XSS的模糊测试之道

    富文本存储型XSS的模糊测试之道 凭借黑吧安全网漏洞报告平台的公开案例数据,我们足以管中窥豹,跨站脚本漏洞(Cross-site Script)仍是不少企业在业务安全风险排查和修复过程中需要对抗的“大 ...

  4. Django模型和ORM

    一.ORM ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是 ...

  5. Django-自动HTML转义

    一.自动HTML转义 从模板生成HTML时,总会有变量包含影响最终HTML的字符风险,例如,考虑这个模板的片段: Hello, {{ name }} 起初,这是一种显示用户名的无害方式,但考虑用户输入 ...

  6. Intel大坑之一:丢失的SSE2 128bit/64bit 位移指令,马航MH370??

    缘由 最近在写一些字符串函数的优化,兴趣使然,可是写的过程中,想要实现 128bit 的按 bit 逻辑位移,遇到了一个大坑,且听我娓娓道来. 如果要追究标题,更确切的是丢失的SSE2 128 bit ...

  7. InnoDB锁问题

    InnoDB锁问题 InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我 ...

  8. Oracle 函数 “判断数据表中不存在的数据,才允许通过”

    create or replace function mca_detail_material_val(p_material_code VARCHAR2, --实参 p_material_name VA ...

  9. python基础学习之路No.5 数学函数以及操作

    python的基本数学函数 函数 返回值 ( 描述 ) abs(x) 返回数字的绝对值,如abs(-10) 返回 10 ceil(x) 返回数字的上入整数,如math.ceil(4.1) 返回 5 c ...

  10. Codeforces 682C Alyona and the Tree (树上DFS+DP)

    题目链接:http://codeforces.com/problemset/problem/682/C 题目大意:取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么 ...