You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CSharpCodeProvider动态编译运行C#字符串代码时,如何访问当前项目窗体及类的控件

解决动态编译C#代码访问当前窗体成员的问题

我之前也踩过这个坑,用CSharpCodeProvider动态编译代码时,默认情况下动态生成的程序集和你的窗体类不在同一个上下文,而且没有办法直接访问当前窗体的实例,所以才会出现无法访问textBox1这类控件的情况。下面给你一套完整的解决方案:

核心思路

要让动态代码能访问当前窗体的成员,需要做到两点:

  • 动态编译时引用当前项目的程序集,让动态代码能识别你的窗体类型
  • 把当前窗体的实例传递给动态执行的代码,这样就能通过实例访问控件和成员

完整代码实现

private void btncompiler_Click(object sender, EventArgs e)
{
    string str = @"
        using System;
        using System.Windows.Forms;

        public class DynamicCodeExecutor
        {
            public void Execute(YourFormType form)
            {
                // 这里可以直接通过form实例访问窗体的成员
                int a = 3;
                int b = 5;
                // 注意控件操作要在UI线程,所以需要Invoke
                if (form.textBox1.InvokeRequired)
                {
                    form.textBox1.Invoke(new Action(() => 
                    {
                        form.textBox1.Text = (a + b).ToString();
                    }));
                }
                else
                {
                    form.textBox1.Text = (a + b).ToString();
                }
            }
        }";

    // 1. 设置编译参数
    var compilerParams = new CompilerParameters();
    // 添加必要的程序集引用
    compilerParams.ReferencedAssemblies.Add("System.dll");
    compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll");
    // 关键:引用当前项目的程序集,这样动态代码能识别你的窗体类型
    compilerParams.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly().Location);
    // 生成内存中的程序集,不用写到磁盘
    compilerParams.GenerateInMemory = true;

    // 2. 编译代码
    var codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
    CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, str);

    // 3. 检查编译错误
    if (results.Errors.HasErrors)
    {
        StringBuilder errorMsg = new StringBuilder();
        foreach (CompilerError error in results.Errors)
        {
            errorMsg.AppendLine($"错误行{error.Line}: {error.ErrorText}");
        }
        MessageBox.Show(errorMsg.ToString());
        return;
    }

    // 4. 加载编译后的程序集并执行代码
    Assembly assembly = results.CompiledAssembly;
    Type executorType = assembly.GetType("DynamicCodeExecutor");
    object executorInstance = Activator.CreateInstance(executorType);
    // 关键:把当前窗体实例传递给动态方法
    executorType.GetMethod("Execute").Invoke(executorInstance, new object[] { this });
}

关键细节说明

  • 替换YourFormType:把代码里的YourFormType换成你实际的窗体类名(比如你的窗体叫MainForm,就改成MainForm)
  • 引用当前程序集:通过System.Reflection.Assembly.GetExecutingAssembly().Location获取当前项目的程序集路径,添加到引用中,这样动态代码就能识别你的窗体类型
  • 传递窗体实例:动态方法Execute接收窗体实例参数,通过这个实例就能访问窗体上的所有控件和成员
  • UI线程安全:因为动态代码可能在非UI线程执行,所以操作控件时要判断InvokeRequired,确保在UI线程更新控件

额外提示

如果你的动态代码需要访问更多类成员,只需要在Execute方法里通过传递的窗体实例直接调用即可,比如form.YourCustomMethod()或者form.YourPublicProperty。

内容的提问来源于stack exchange,提问作者ame teaser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:14:09