动态执行 VB.NET 和 C# 代码

简介: 原文:动态执行 VB.NET 和 C# 代码有时候我们需要尝试动态地与一些代码进行交互,而不是只能执行程序内已编死的代码,那该怎么办呢?我首先推荐各种脚本语言,如Javascript、Lua、Python等等,这些脚本语言有很多优秀的第三方类库,可以很方便的与 .NET 系统集成,让我们的程序中执行动态代码。
原文: 动态执行 VB.NET 和 C# 代码

有时候我们需要尝试动态地与一些代码进行交互,而不是只能执行程序内已编死的代码,那该怎么办呢?
我首先推荐各种脚本语言,如Javascript、Lua、Python等等,这些脚本语言有很多优秀的第三方类库,可以很方便的与 .NET 系统集成,让我们的程序中执行动态代码。

但如果你一定想用VB.NET或者C#的代码来运行一段程序,这里就要用到动态编译的功能了。

下面是我写的两个实例,你只需要在窗体 FormMain 中添加一个 button 和一个 textbox 即可,默认名为 Button1TextBox1

VB.NET代码

Imports System.CodeDom.Compiler
Imports System.Reflection

Public Class FormMain

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' 编译参数
        Dim cpars As New CompilerParameters

        ' 编译参数,如 /optimize /removeintchecks 等
        cpars.CompilerOptions = "/optimize "

        cpars.GenerateInMemory = True '在内存中编译而不输出文件
        cpars.GenerateExecutable = False '并不输出执行文件
        cpars.IncludeDebugInformation = False '不需要调试信息

        ' 导入类库(根据自己代码的需要导入)
        cpars.ReferencedAssemblies.Add("mscorlib.dll")
        cpars.ReferencedAssemblies.Add("System.dll")
        cpars.ReferencedAssemblies.Add("System.Data.dll")
        cpars.ReferencedAssemblies.Add("System.Deployment.dll")
        cpars.ReferencedAssemblies.Add("System.Drawing.dll")
        cpars.ReferencedAssemblies.Add("System.Windows.Forms.dll")
        cpars.ReferencedAssemblies.Add("System.Xml.dll")
        cpars.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")

        ' 编译参数,为导入的类库设置全局引用(否则必须使用完整的命名空间名称才能正确调用函数)
        cpars.CompilerOptions &= " /imports:" & _
         "Microsoft.VisualBasic," & _
         "System," & _
         "System.Collections," & _
         "System.Collections.Generic," & _
         "System.Drawing," & _
         "System.Windows.Forms"

        ' 设置编译器
        Dim vbc As New VBCodeProvider
        'Dim vbc = CodeDomProvider.CreateProvider("VisualBasic") '等效方法

        ' 一个简单的模板类
        Dim codex As String = _
         "Public Class CompClass" & vbCrLf & _
         "    Shared Function RunCode() As Object" & vbCrLf & _
         "        '$" & vbCrLf & _
         "    End Function" & vbCrLf & _
         "End Class"

        ' 替换代码到模板类中
        Dim code As String = codex.Replace("'$", TextBox1.Text)


        ' 编译并返回
        Dim resut As CompilerResults = vbc.CompileAssemblyFromSource(cpars, code)

        ' 如果发生了错误
        If resut.Errors.Count > 0 Then
            MsgBox(resut.Errors(0).ToString)
            Return
        End If


        ' 尝试调用代码
        Dim asm As Assembly = resut.CompiledAssembly '获取程序集

        ' 获取我们编写的静态方法
        Dim mi As MethodInfo = asm.GetType("CompClass").GetMethod("RunCode")

        ' 执行代码,并获取返回值
        Dim ret As Object = mi.Invoke(Nothing, Nothing)

        ' 对返回值进行处理
        If ret IsNot Nothing Then
            MsgBox(ret.ToString)
        End If

    End Sub

End Class

执行程序,在 Textbox1 里写入一些VB代码,按 Button1 即可立即执行里面的代码。
如果拥有返回值,程序还可以获取代码的返回值,但有可能需要你进行拆箱处理。

C#代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Reflection;
using System.CodeDom.Compiler;

namespace WindowsFormsApplication1
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            // 编译参数
            var cpars = new CompilerParameters();
            cpars.CompilerOptions = "/optimize ";
            cpars.GenerateInMemory = true;
            cpars.GenerateExecutable = false;
            cpars.IncludeDebugInformation = false;

            // 导入类库(根据自己代码的需要导入)
            cpars.ReferencedAssemblies.Add("mscorlib.dll");
            cpars.ReferencedAssemblies.Add("System.dll");
            cpars.ReferencedAssemblies.Add("System.Data.dll");
            cpars.ReferencedAssemblies.Add("System.Deployment.dll");
            cpars.ReferencedAssemblies.Add("System.Drawing.dll");
            cpars.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            cpars.ReferencedAssemblies.Add("System.Xml.dll");

            // 编译器实例
            var csc = new Microsoft.CSharp.CSharpCodeProvider();
            //var csc = CodeDomProvider.CreateProvider("CSharp");

            // 一个简单的模板类
            // 因为C#的编译器无法设置全局命名空间,所以需要在代码中导入命名空间
            var codex = @"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
class CompClass{
    static public object RunCode(){
        //$
        return null;
    }
}
";

            // 替换代码到模板类中
            var code = codex.Replace("//$", TextBox1.Text);

            // 编译并返回
            var resut = csc.CompileAssemblyFromSource(cpars, code);

            // 错误警告
            if (resut.Errors.Count > 0) {
                MessageBox.Show(resut.Errors[0].ToString());
                return;
            }

            // 调用代码
            var asm = resut.CompiledAssembly;
            var mi = asm.GetType("CompClass").GetMethod("RunCode");

            object ret = mi.Invoke(null, null);
            if (ret != null) {
                MessageBox.Show(ret.ToString());
            }
        }
    }
}

C#的代码流程与VB的基本相同,区别在于C#的编译器没有导入全局命名空间的参数,因此需要在模板类里写入你需要导入的命名空间。
其他的用法基本都一样。

PS: 我有空再写一点与第三方脚本库进行交互的代码示例。

 

 

目录
相关文章
|
27天前
|
开发框架 搜索推荐 算法
一个包含了 50+ C#/.NET编程技巧实战练习教程
一个包含了 50+ C#/.NET编程技巧实战练习教程
94 18
|
27天前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
57 13
|
27天前
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
66 12
|
25天前
|
开发框架 人工智能 .NET
C#/.NET/.NET Core拾遗补漏合集(24年12月更新)
C#/.NET/.NET Core拾遗补漏合集(24年12月更新)
|
25天前
|
开发框架 算法 .NET
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
|
25天前
|
开发框架 Cloud Native .NET
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
|
1月前
|
开发框架 监控 .NET
C#进阶-ASP.NET WebForms调用ASMX的WebService接口
通过本文的介绍,希望您能深入理解并掌握ASP.NET WebForms中调用ASMX WebService接口的方法和技巧,并在实际项目中灵活运用这些技术,提高开发效率和应用性能。
55 5
|
1月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
133 13
|
1月前
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
2月前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)