AssemblyLoadContext 的研究笔记

关于 .NET AssemblyLoadContext 的研究笔记

   public class MyAssemblyLoadContext : AssemblyLoadContext
   {
       private readonly AssemblyDependencyResolver _resolver;

       public MyAssemblyLoadContext(string pluginDllPath) : base(isCollectible: true)
       {
           // 传入的是“主程序集”路径,resolver 会自动找同名的 .deps.json
           _resolver = new AssemblyDependencyResolver(pluginDllPath);
       }

       // 2. 只要插件里出现“using xxx;”,运行时就会走到这里
       protected override Assembly? Load(AssemblyName name)
       {
           string? path = _resolver.ResolveAssemblyToPath(name);
           if (path != null) return LoadFromAssemblyPath(path);

           return null; // 返回 null 会让运行时继续默认逻辑
       }

       // 3. 非托管 dll (sqlite、libuv …) 同理
       protected override IntPtr LoadUnmanagedDll(string unmanagedName)
       {
           string? path = _resolver.ResolveUnmanagedDllToPath(unmanagedName);
           return path != null ? LoadUnmanagedDllFromPath(path) : IntPtr.Zero;
       }
   }
    internal class Program
    {
        private static AssemblyLoadContext _alc;

        static void ALCLoadLib1()
        {
            ALCUnload();

            var file = @"G:\fanbalcode\testwebswagger\ALCHost\Lib1\bin\Debug\net8.0\publish\Lib1.dll";
            var myALC = new MyAssemblyLoadContext(file);
            myALC.LoadFromAssemblyPath(file);

            _alc = myALC;
        }
        static void ALCLoadLib2()
        {
            ALCUnload();

            var file = @"G:\fanbalcode\testwebswagger\ALCHost\Lib2\bin\Debug\net8.0\publish\Lib2.dll";
            var myALC = new MyAssemblyLoadContext(file);
            myALC.LoadFromAssemblyPath(file);

            _alc = myALC;
        }

        static void ALCUnload()
        {
            if (_alc is not null) _alc.Unload();
        }

        private static WeakReference GetStudent()
        {
            var studentType = _alc.Assemblies.Select(i => i.GetType("Lib.Student")).FirstOrDefault(i => i is not null);
            var studentIns = Activator.CreateInstance(studentType);
            return new WeakReference(studentIns);
        }

        static void Main(string[] args)
        {
            ALCLoadLib1();
            var student1 = GetStudent();

            ALCLoadLib2();
            var student2 = GetStudent();

            Console.WriteLine(student2);

            // 2. 持续 GC 直到确认释放
            for (int i = 0; i < 10 && student1.IsAlive; i++)
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                Console.WriteLine($"GC #{i + 1}: " + student1.IsAlive);
            }
        }


    }

通过 AssemblyLoadContext 可以实现可卸载的插件系统,对于游戏的热更新或者一些强调扩展性的软件开发有着重要的意义。

posted @ 2025-11-28 11:12  fanbal  阅读(7)  评论(0)    收藏  举报