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

如何阻止Godot C#重复加载公共库的额外实例

Godot中C#插件加载时公共库重复加载导致类型不匹配的解决方案

当在Godot中加载引用公共库的C#插件时,若主程序与插件共用同一公共库,常会出现公共库被重复加载的情况。这会导致主程序中的公共类型(如示例里的ICommonInterface)与插件中的同名义类型无法被CLR识别为同一类型,进而出现IsAssignableTo判断失败的问题——本质原因是Godot主程序加载公共库的上下文与手动加载插件时的上下文不一致,CLR会将同一路径的库视为不同的程序集实例。

以下是针对性的解决方案:

1. 复用Godot主程序的加载上下文

不要使用Assembly.LoadFrom加载插件,而是通过Godot主程序使用的默认AssemblyLoadContext来加载,这样会自动复用已加载的公共库实例:

修改主程序中的加载代码:

var commonType = typeof(ICommonInterface);
// 获取Godot主程序使用的默认加载上下文
var defaultLoadContext = System.Runtime.Loader.AssemblyLoadContext.Default;
// 确保插件路径是绝对路径(这里假设Plugin.dll在项目根目录)
var pluginPath = Path.Combine(ProjectSettings.GlobalizePath("res://"), "Plugin.dll");
var pluginAssembly = defaultLoadContext.LoadFromAssemblyPath(pluginPath);

foreach (var type in pluginAssembly.ExportedTypes)
{
    if (type.IsAssignableTo(commonType))
    {
        // 现在可以正常识别匹配的类型
        GD.Print($"匹配到实现ICommonInterface的类型:{type.Name}");
    }
}

2. 统一公共库的部署路径

  • 将公共库Library.dll放在Godot项目的输出目录(如bin/Debug/net6.0/),确保主程序和插件都指向该路径的库文件。
  • 在插件项目的引用设置中,将Library.dll的"复制到输出目录"设置为不复制,避免插件目录中生成重复的库文件,触发CLR重复加载。

3. 排查重复加载情况(调试用)

如果问题仍存在,可以通过以下代码查看当前已加载的程序集,确认是否存在重复加载的Library.dll:

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    if (assembly.GetName().Name.Equals("Library", StringComparison.Ordinal))
    {
        GD.Print($"已加载的Library程序集:路径={assembly.Location},实例哈希={assembly.GetHashCode()}");
    }
}

若输出多个不同的哈希值,说明确实存在重复加载,需要检查加载方式或部署路径是否正确。

4. 自定义加载上下文(进阶控制)

如果需要对插件加载进行更精细的控制,可以创建自定义AssemblyLoadContext,强制共享公共库:

public class PluginSharedLoadContext : System.Runtime.Loader.AssemblyLoadContext
{
    public PluginSharedLoadContext() : base(isCollectible: false) { }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        // 公共库从默认上下文加载,避免重复
        if (assemblyName.Name.Equals("Library", StringComparison.Ordinal))
        {
            return System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName);
        }
        // 其他程序集按默认逻辑加载
        return base.Load(assemblyName);
    }
}

// 使用自定义上下文加载插件
var sharedLoadContext = new PluginSharedLoadContext();
var pluginAssembly = sharedLoadContext.LoadFromAssemblyPath(pluginPath);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:03:15