如何阻止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
相关产品推荐
相关产品推荐

