c# - 在 .NET 中重新加载程序集而不创建新的 AppDomain

标签 c# .net .net-assembly

我正在使用 C# 开发游戏引擎 + 编辑器。这个想法是用户将他所有的游戏代码写在一个项目中,然后编辑器将加载该项目,因此它可以列出用户定义的类,并在场景编辑器中实例化它们。

利用(重新)加载 DLL 的概念,我可以加载 DLL,在外部程序集中定义的类上实例化和调用方法,重建外部程序集,然后在主机中再次加载它,而无需重新启动主人。这项工作(至少看起来像),但它并没有从先前加载的程序集中释放内存。

加载器类:

public class Loader
{
    // This DLL contains an implementation of ILoadable - ILoadable is declared in a shared project.
    private const string AsmPath = @"D:\Dev\AsmLoading\AsmLoadingImpl\bin\Debug\AsmLoadingImpl.dll";

    public ILoadable GetExternalLoadable()
    {
        var asmBytes = File.ReadAllBytes(AsmPath);
        Assembly asm = Assembly.Load(asmBytes, null);
        var loadableInterface = typeof(ILoadable);
        var loadableImpl = asm.GetTypes().First(loadableInterface.IsAssignableFrom);
        return (ILoadable)Activator.CreateInstance(loadableImpl);
    }
}

运行 GetExternalLoadable() 2 或 3 次,任务管理器显示我的主机程序中的 RAM 使用量增加了 ~1mb,重复相同的操作会进一步增加它,而不会减少。

有什么办法可以解决这个问题吗?我知道 Unity 正在做类似的事情,除了他们实际上自己编译外部程序集,但是当我触发几次重新编译时,Unity 编辑器不会消耗额外的内存。

所以,我想要完成的是外部程序集的“实时重新加载”

最佳答案

.NET 4 添加了对 collectible assemblies 的支持, 可以被 GC 卸载。

但是,这些受到严格限制:

  • 它们用于动态代码生成,您不能只加载一个 .dll 文件
  • 他们不能定义 COM 互操作类型、P/Invoke 方法、线程静态字段......

如果您有一个遵循这些限制的 .dll,您可能能够加载并重新发出 IL 代码,这样它看起来就像一个动态生成的 .NET 程序集。

除了动态方法和可收集的程序集之外,不可能在不卸载整个 AppDomain 的情况下卸载代码。

关于c# - 在 .NET 中重新加载程序集而不创建新的 AppDomain,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25669119/

相关文章:

c# - 设置包含对其他复杂对象的循环引用的复杂对象以进行单元测试

c# - 具有 LDAP 身份验证的 Asp.Net Core 2.1 身份

C# 可空字符串错误

c# - 异步套接字-与C#中的永久套接字的双工通信

c# - C# 或 .NET 中最糟糕的陷阱是什么?

c# - 不同的 DLL,但在控制台应用程序和网站中应该相同

c# - .Net 命名空间可以跨越多个程序集吗?

c# - 在 C# 中锁定静态方法

.net - 作为 .NET 开发人员,我如何开始使用 Sparql?

c# - 如果静态类加载失败会发生什么