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

在C#程序中动态编译运行外部代码遇System.Runtime引用错误

动态编译学生代码时System.Runtime引用错误的解决方法

问题背景

我需要在TeacherCode.cs类中,通过反射和Roslyn动态编译并运行学生的StudentCode.cs代码。核心需求是检查学生代码中是否存在名为Print的方法,若存在则调用该方法(后续还需扩展检查递归、循环等代码结构)。但编译过程中出现以下错误:

Compilation failed:
(8,17): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
(8,9): error CS0012: The type 'Decimal' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

学生代码(StudentCode.cs)

// StudentCode.cs
using System;

public class StudentClass
{
    public static void Print()
    {
        Console.WriteLine("Hello from StudentClass.Print!");
    }
}

教师代码(TeacherCode.cs)

// TeacherCode.cs
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

public class Checker
{
    public static void Main(string[] args)
    {
        // Path to the student's code file
        string filePath = "StudentCode.cs";

        if (!File.Exists(filePath))
        {
            Console.WriteLine("File not found: " + filePath);
            return;
        }
    
        string studentCode = File.ReadAllText(filePath);
    
        // Check if 'Print' method exists, and if so, invoke it
        CheckAndInvoke(studentCode, "Print");
    }
    
    static void CheckAndInvoke(string code, string methodName)
    {
        var syntaxTree = CSharpSyntaxTree.ParseText(code);
        var compilation = CSharpCompilation.Create("StudentCode",
            new[] { syntaxTree },
            new[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location)
            },
            new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
    
        using (var ms = new MemoryStream())
        {
            var result = compilation.Emit(ms);
    
            if (!result.Success)
            {
                Console.WriteLine("Compilation failed:");
                foreach (var diagnostic in result.Diagnostics)
                {
                    Console.WriteLine(diagnostic.ToString());
                }
                return;
            }
    
            ms.Seek(0, SeekOrigin.Begin);
            var assembly = Assembly.Load(ms.ToArray());
    
            // Find the class and method
            var type = assembly.GetTypes().FirstOrDefault();
            if (type != null)
            {
                var method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public);
                if (method != null)
                {
                    // Invoke the Print method
                    method.Invoke(null, null);
                }
                else
                {
                    Console.WriteLine("Method 'Print' not found in compiled assembly.");
                }
            }
            else
            {
                Console.WriteLine("No classes found in the compiled assembly.");
            }
        }
    }
}

错误原因与解决办法

在.NET 6及以上的SDK风格项目中,object、decimal等基础类型不再定义在传统的mscorlib.dll中,而是移到了System.Runtime.dll里。当前的编译引用缺少这个关键程序集,导致类型无法解析。

只需在编译引用数组中添加System.Runtime的引用即可解决问题,有两种简洁的方式:

方式一:通过decimal类型获取引用

直接利用错误提示中提到的Decimal类型来定位程序集:

var compilation = CSharpCompilation.Create("StudentCode",
    new[] { syntaxTree },
    new[]
    {
        MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location),
        // 添加System.Runtime引用
        MetadataReference.CreateFromFile(typeof(decimal).Assembly.Location)
    },
    new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

方式二:通过编译器特性类型获取引用

使用.NET中的标记类型来定位System.Runtime:

var compilation = CSharpCompilation.Create("StudentCode",
    new[] { syntaxTree },
    new[]
    {
        MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location),
        // 添加System.Runtime引用
        MetadataReference.CreateFromFile(typeof(System.Runtime.CompilerServices.IsExternalInit).Assembly.Location)
    },
    new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

添加引用后,编译就能正常解析Object和Decimal类型,顺利完成编译并调用Print方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 05:12:36