【问题标题】:Reloading assemblies in .NET without creating a new AppDomain在 .NET 中重新加载程序集而不创建新的 AppDomain
【发布时间】:2014-09-04 15:14:05
【问题描述】:

我正在使用 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 编辑器不会消耗额外的内存。

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

【问题讨论】:

  • 可能 unity 正在使用单独的应用程序域来运行这些程序集 :) 来自:msdn.microsoft.com/en-gb/library/ms173101.aspx 如果不卸载包含它的所有应用程序域,就无法卸载单个程序集。即使程序集超出范围,实际的程序集文件仍将保持加载,直到包含它的所有应用程序域都被卸载。
  • @OndrejSvejdar 是什么让你这么认为? :)
  • 如果要卸载程序集,唯一的方法是使用新的 AppDomain 并卸载该 AppDomain。
  • @mikez 是的,我知道,只是想知道是否有其他方法。
  • @OndrejSvejdar 我只是查看了 Unity 对象树,但没有一个 [Serializable]MarshalByRefObject :)

标签: c# .net .net-assembly


【解决方案1】:

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

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

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

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

除了动态方法和可收集的程序集,不卸载整个 AppDomain 是不可能卸载代码的。

【讨论】:

  • 那就不行了。你知道我可以用 AppDomains 来实现与我在 OP 中发布的 Loader 类相同的结果吗?
  • 回到这个答案,我如何能够加载并重新发出 DLL?
  • @Daniel 是的,您有如何实施重新排放的示例吗?
猜你喜欢
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多