博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 动态类型与动态编译简介
阅读量:7262 次
发布时间:2019-06-29

本文共 4868 字,大约阅读时间需要 16 分钟。

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

动态类型

  • 关键字: dynamic
    这里有详细的介绍:

动态类型的应用场景

  1. 可以减少强制转换(强制转换其实挺好的,让程序猿清楚地指定自己做了什么,不至于出错时不知所措)
  2. 简化反射的写法。
  3. 与动态语言交互。
// 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#同样支持动态编译。

最主要的两个类:

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的性能问题,可以参看这里:


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;}

转载于:https://www.cnblogs.com/jasongrass/p/10433346.html

你可能感兴趣的文章
runc容器逃逸漏洞最强后续:应对之策汇总与热点疑问解答
查看>>
JS实例学习笔记——w3cschool+菜鸟教程
查看>>
ubuntu下Nginx详解及点播直播服务器搭建
查看>>
Webpack DLL 配置教程
查看>>
构造函数创建私有变量(防继承)
查看>>
Why Kubernetes ,我所理解的docker与k8s
查看>>
Transformer-XL: Unleashing the Potential of Attention Models
查看>>
极限编程 (Extreme Programming) - 发布计划 (Release Planning)
查看>>
Ghost配置6——首页太阳系动画效果
查看>>
Problem 4:替换空格(字符串)
查看>>
如何使用Tunnel SDK上传/下载MaxCompute复杂类型数据
查看>>
SpiderData 2019年2月15日 DApp数据排行榜
查看>>
javascript 面向对象 new 关键字 原型链 构造函数
查看>>
算法与数据结构大系列 - NO.1 - 插入排序
查看>>
我的2018
查看>>
leetcode394. Decode String
查看>>
241. Different Ways to Add Parentheses
查看>>
前嗅ForeSpider教程:字段的取值与清洗
查看>>
react native 原生模块桥接的简单说明
查看>>
Spring Boot 单元测试二三事
查看>>