ModuleDef LoadDynamicModule(DbgModule module)
        {
            if (module == null)
            {
                throw new ArgumentNullException(nameof(module));
            }

            var doc = FindDynamicModule(module);

            if (doc != null)
            {
                return(doc);
            }

            if (!TryGetRuntimeInfo(module.Runtime, out var info))
            {
                return(null);
            }
            if (info.DynamicModuleProvider == null)
            {
                return(null);
            }

            if (module.Process.State != DbgProcessState.Paused)
            {
                return(null);
            }

            // Can happen if the breakpoints window just opened and a dynamic assembly is requested.
            if (uiDispatcher.IsProcessingDisabled())
            {
                return(null);
            }

            lock (lockObj) {
                doc = FindDynamicModule(module);
                if (doc != null)
                {
                    return(doc);
                }

                var modules = info.AssemblyInfoProvider.GetAssemblyModules(module);
                if (modules.Length == 0)
                {
                    return(null);
                }
                var manifestDnModule = modules[0];
                var manifestKey      = DynamicModuleDefDocument.CreateKey(manifestDnModule);
                var manMod           = FindDocument(manifestKey);
                Debug.Assert(manMod == null);
                if (manMod != null)
                {
                    return(null);
                }

                var manDoc = FindDynamicModule(manifestDnModule);
                Debug.Assert(manDoc == null);
                if (manDoc != null)
                {
                    return(null);
                }

                var files = new List <DynamicModuleDefDocument>(modules.Length);
                DynamicModuleDefDocument resDoc = null;
                foreach (var m in modules)
                {
                    var md = info.DynamicModuleProvider.GetDynamicMetadata(m, out var moduleId);
                    if (md == null)
                    {
                        continue;
                    }
                    UpdateResolver(md);
                    var newDoc = new DynamicModuleDefDocument(moduleId, m, md, UseDebugSymbols);
                    if (m == module)
                    {
                        resDoc = newDoc;
                    }
                    files.Add(newDoc);
                }
                if (files.Count == 0)
                {
                    return(null);
                }
                Initialize(info, files.ToArray());

                var asmFile   = DynamicModuleDefDocument.CreateAssembly(files);
                var addedFile = documentProvider.GetOrAdd(asmFile);
                Debug.Assert(addedFile == asmFile);

                return(resDoc?.ModuleDef);
            }
        }
        void OnModuleAdded_UI(RuntimeInfo info, DbgModule manifestModule, DbgModule module)
        {
            uiDispatcher.VerifyAccess();

            // If an assembly is visible in the treeview, and a new netmodule gets added, add a
            // new netmodule node to the assembly in the treeview.

            // Update a dynamic assembly, if one exists
            if (info.DynamicModuleProvider != null)
            {
                var manifestKey = DynamicModuleDefDocument.CreateKey(manifestModule);
                var asmFile     = FindDocument(manifestKey);
                if (documentTreeView.Value.FindNode(asmFile) is AssemblyDocumentNode asmNode)
                {
                    var moduleKey = DynamicModuleDefDocument.CreateKey(module);
                    asmNode.TreeNode.EnsureChildrenLoaded();
                    Debug.Assert(asmNode.TreeNode.Children.Count >= 1);
                    var moduleNode = asmNode.TreeNode.DataChildren.OfType <ModuleDocumentNode>().FirstOrDefault(a => moduleKey.Equals(a.Document.Key));
                    Debug.Assert(moduleNode == null);
                    if (moduleNode == null)
                    {
                        var md = info.DynamicModuleProvider.GetDynamicMetadata(module, out var moduleId);
                        if (md != null)
                        {
                            UpdateResolver(md);
                            var newFile = new DynamicModuleDefDocument(moduleId, module, md, UseDebugSymbols);
                            asmNode.Document.Children.Add(newFile);
                            Initialize_UI(info, new[] { newFile });
                            asmNode.TreeNode.Children.Add(documentTreeView.Value.TreeView.Create(documentTreeView.Value.CreateNode(asmNode, newFile)));
                        }
                    }
                }
            }

            // Update an in-memory assembly, if one exists
            if (manifestModule.HasAddress && module.HasAddress)
            {
                var manifestKey = MemoryModuleDefDocument.CreateKey(manifestModule.Process, manifestModule.Address);
                var asmFile     = FindDocument(manifestKey);
                if (documentTreeView.Value.FindNode(asmFile) is AssemblyDocumentNode asmNode)
                {
                    var moduleKey = MemoryModuleDefDocument.CreateKey(module.Process, module.Address);
                    asmNode.TreeNode.EnsureChildrenLoaded();
                    Debug.Assert(asmNode.TreeNode.Children.Count >= 1);
                    var moduleNode = asmNode.TreeNode.DataChildren.OfType <ModuleDocumentNode>().FirstOrDefault(a => moduleKey.Equals(a.Document.Key));
                    Debug.Assert(moduleNode == null);
                    if (moduleNode == null)
                    {
                        MemoryModuleDefDocument newFile = null;
                        try {
                            newFile = MemoryModuleDefDocument.Create(this, module, UseDebugSymbols);
                        }
                        catch {
                        }

                        Debug.Assert(newFile != null);
                        if (newFile != null)
                        {
                            UpdateResolver(newFile.ModuleDef);
                            asmNode.Document.Children.Add(newFile);
                            RemoveFromAssembly(newFile.ModuleDef);
                            asmNode.Document.ModuleDef.Assembly.Modules.Add(newFile.ModuleDef);
                            asmNode.TreeNode.Children.Add(documentTreeView.Value.TreeView.Create(documentTreeView.Value.CreateNode(asmNode, newFile)));
                        }
                    }
                }
            }
        }