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

Roslyn Emit API生成的DLL无法引用,如何非反射调用?

使用Roslyn生成DLL后直接引用失败的解决方法

问题描述

我通过Roslyn Emit API生成了.dll文件,生成操作显示成功,但在另一个项目中直接引用该.dll时,抛出System.IO.FileNotFoundException异常,提示找不到程序集“HelloDll”或其依赖项。使用反射加载DLL的方式可以正常工作,但希望无需反射直接调用DLL中的类型。

生成DLL的代码

static void compileToDll()
{
    string codeDll = @"""
    using System;

    public class MyClass
    {
         public static void RunIt(FEE_BoolSlot slot)
         {
              Console.WriteLine("""Hello World!""");
         }
     }
 """;

    var tree = CSharpSyntaxTree.ParseText(codeDll);
    var root = (CompilationUnitSyntax)tree.GetRoot();

    var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
    options = options.WithPlatform(Platform.AnyCpu);

    var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
    var compilation = CSharpCompilation.Create(
                         "HelloDll", 
                         options:options, 
                         references: new[] { mscorlib })
                    .AddSyntaxTrees(tree);

    var r = compilation.Emit("example.dll");
}

消费DLL的代码(报错)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

class Main
{
    static void Main(string[] args)
    {
        MyClass2.RunIt();
        // 下面这行可以正常工作
        // var assembly = Assembly.LoadFile("C:\\...\\example.dll");
    }
}

解决步骤

1. 修正生成代码的语法错误与依赖

  • 字符串转义错误:codeDll的定义存在语法问题,@"""会导致生成的代码开头多一个引号,正确写法应该是用@"开头,内部双引号用两个双引号转义:
    string codeDll = @"
    using System;
    
    public class MyClass
    {
         public static void RunIt(FEE_BoolSlot slot)
         {
              Console.WriteLine(""Hello World!"");
         }
     }
    ";
    
  • 缺失依赖引用:代码中使用了FEE_BoolSlot类型,但当前编译仅引用了mscorlib。如果该类型来自其他程序集,必须添加对应的MetadataReference,否则生成的DLL会有未解决的依赖,导致引用失败:
    // 示例:添加包含FEE_BoolSlot的程序集引用
    var feeAssembly = MetadataReference.CreateFromFile(typeof(FEE_BoolSlot).Assembly.Location);
    var compilation = CSharpCompilation.Create(
                         "HelloDll", 
                         options:options, 
                         references: new[] { mscorlib, feeAssembly })
                    .AddSyntaxTrees(tree);
    
  • 检查编译结果:调用Emit后,务必检查返回结果是否成功,若失败则查看编译诊断信息:
    var r = compilation.Emit("example.dll");
    if (!r.Success)
    {
        foreach (var diag in r.Diagnostics)
        {
            Console.WriteLine(diag.ToString());
        }
    }
    

2. 确保DLL被消费项目正确识别

  • 正确引用DLL:在消费项目中右键“添加引用”,浏览到生成的example.dll文件,确保引用路径正确,并且在引用的属性中将“复制本地”设置为True,这样DLL会被复制到消费项目的输出目录。
  • 类型名称匹配:消费代码中调用的MyClass2与生成的类名MyClass不匹配,需修正为MyClass.RunIt(/* 传入FEE_BoolSlot实例 */);,同时消费项目也需要引用包含FEE_BoolSlot的程序集,否则编译时会找不到该类型。

3. 保证DLL路径可被加载

  • 生成DLL时最好指定绝对路径,避免相对路径导致的文件找不到问题:
    var outputPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "example.dll");
    var r = compilation.Emit(outputPath);
    
  • 如果生成DLL的程序与消费项目分离,需手动将example.dll复制到消费项目的输出目录(如bin/Debug/net6.0),或者通过构建事件自动复制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 16:11:21