C# 动态编译简介

C# 动态类型与动态编译简介

动态类型

动态编译

CSScript

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

动态类型

关键字:dynamic

这里有详细的介绍:[C#基础知识系列]专题十七:深入理解动态类型

动态类型的应用场景

可以减少强制转换(强制转换其实挺好的,让程序猿清楚地指定自己做了什么,不至于出错时不知所措)

简化反射的写法。

与动态语言交互。

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

详细下介绍可以看这里:

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;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值