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

使用HostFXR托管可热加载用户C#程序集的C#运行时遇加载异常

问题原因

当UserLibrary.dll调用FunctionLibrary.Module.Test时,CLR无法找到FunctionLibrary.dll。虽然Host.dll已引用并加载了FunctionLibrary,但通过Assembly.Load(byte[])动态加载的UserLibrary,其依赖解析逻辑不会自动复用Host已加载的程序集,也无法定位到FunctionLibrary的存放路径,最终导致找不到依赖的程序集。

解决方案

方案1:注册程序集解析回调

在Host的Main方法开头注册AssemblyResolve事件,当CLR找不到依赖时,手动指定路径加载目标程序集,或返回已加载的程序集:

using System.Reflection;
using System.Runtime.InteropServices;
using System.Linq;

namespace Host;

public unsafe class Program
{
    private static byte[] ToMemoryStream( Stream input )
    {
        MemoryStream ms = new MemoryStream();
        input.CopyTo( ms );
        return ms.ToArray();
    }

    private static Assembly LoadAssembly( string path )
    {
        return Assembly.Load( ToMemoryStream( File.OpenRead( path ) ) );
    }

    [UnmanagedCallersOnly]
    public static void Main()
    {
        // 注册程序集解析回调
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            // 匹配FunctionLibrary的请求
            if (args.Name.StartsWith("FunctionLibrary,"))
            {
                // 替换为FunctionLibrary.dll的实际路径
                string libPath = @"W:\Visual Studio 2022\FunctionLibrary\bin\Debug\net7.0\FunctionLibrary.dll";
                // 直接加载文件返回,或返回已加载的程序集
                return Assembly.Load(File.ReadAllBytes(libPath));
                // 可选:返回已加载的程序集,避免重复加载
                // return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name);
            }
            return null;
        };

        try
        {
            FunctionLibrary.Module.Test = true;

            Assembly userLibrary = LoadAssembly( @"W:\Visual Studio 2022\UserLibrary\bin\Debug\net7.0\UserLibrary.dll" );
            Type? userModule = userLibrary.GetType( "MyLibrary.MyModule" );
            MethodInfo entryPoint = userModule?.GetMethod( "OnStartup", BindingFlags.Static | BindingFlags.Public );
            entryPoint.Invoke( null, null );
        }
        catch ( Exception ex )
        {
            Console.WriteLine( ex );
        }
    }
}

此方案无需移动文件,完全通过代码控制依赖加载逻辑。

方案2:将FunctionLibrary.dll放到CLR默认查找路径

CLR默认会从以下位置查找程序集:

  • C++宿主程序的工作目录
  • UserLibrary.dll所在的目录
  • GAC

只需将FunctionLibrary.dll复制到上述任意一个目录(比如UserLibrary.dll所在的W:\Visual Studio 2022\UserLibrary\bin\Debug\net7.0\目录),CLR即可自动找到并加载它。

方案3:使用Assembly.LoadFrom加载UserLibrary

替换LoadAssembly方法为Assembly.LoadFrom,它会自动处理当前程序集目录下的依赖:

private static Assembly LoadAssembly( string path )
{
    return Assembly.LoadFrom(path);
}

此方法操作简单,但会锁定目标文件,且依赖程序集必须与UserLibrary.dll在同一目录下,灵活性不如方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:45:24