public static void Reload([NotNull] SessionViewModel session, ILogger log, Action postReloadAction, Action undoAction, [NotNull] Dictionary <PackageLoadedAssembly, string> modifiedAssemblies) { var loadedAssemblies = modifiedAssemblies.Where(x => File.Exists(x.Key.Path)).ToDictionary(x => x.Key, x => x.Value); var assemblyContainer = session.AssemblyContainer; using (session.CreateAssetFixupContext()) { // TODO: Filter by "modified assemblies", for now we reload everything var loadedAssembliesSet = new HashSet <Assembly>(loadedAssemblies.Select(x => x.Key.Assembly).NotNull()); // Serialize types from unloaded assemblies as Yaml, and unset them var unloadingVisitor = new UnloadingVisitor(log, loadedAssembliesSet); Dictionary <AssetViewModel, List <ItemToReload> > assetItemsToReload; try { assetItemsToReload = PrepareAssemblyReloading(session, unloadingVisitor, session.UndoRedoService); } catch (Exception e) { log.Error("Could not prepare asset for assembly reload", e); throw; } var reloadOperation = new ReloadAssembliesOperation(assemblyContainer, modifiedAssemblies, Enumerable.Empty <IDirtiable>()); session.UndoRedoService.SetName(reloadOperation, "Reload assemblies"); // Reload assemblies reloadOperation.Execute(log); session.UndoRedoService.PushOperation(reloadOperation); postReloadAction(); var postReloadOperation = new AnonymousDirtyingOperation(Enumerable.Empty <IDirtiable>(), postReloadAction, postReloadAction); session.UndoRedoService.PushOperation(postReloadOperation); session.UndoRedoService.SetName(postReloadOperation, "Post reload action"); // Restore deserialized objects (or IUnloadable if it didn't work) var reloadingVisitor = new ReloadingVisitor(log, loadedAssembliesSet); try { PostAssemblyReloading(session.UndoRedoService, session.AssetNodeContainer, reloadingVisitor, log, assetItemsToReload); } catch (Exception e) { log.Error("Could not restore asset after assembly reload", e); throw; } var undoOperation = new AnonymousDirtyingOperation(Enumerable.Empty <IDirtiable>(), undoAction, null); session.UndoRedoService.PushOperation(undoOperation); session.UndoRedoService.SetName(undoOperation, "Undo action"); } session.ActiveProperties.RefreshSelectedPropertiesAsync().Forget(); }
private static void PostAssemblyReloading(IUndoRedoService actionService, SessionNodeContainer nodeContainer, ReloadingVisitor reloaderVisitor, ILogger log, Dictionary <AssetViewModel, List <ItemToReload> > assetItemsToReload) { log?.Info("Updating components with newly loaded assemblies"); // Recreate new objects from Yaml streams foreach (var asset in assetItemsToReload) { // Deserialize objects with reloaded types from Yaml reloaderVisitor.Run(asset.Key.Asset, asset.Value); // Set new values var overrides = new YamlAssetMetadata <OverrideType>(); foreach (var itemToReload in asset.Value) { // Set (members) or add nodes (collections) with values created using newly loaded assemblies ReplaceNode(actionService, asset.Key, itemToReload); if (itemToReload.Overrides != null) { var extendedPath = itemToReload.GraphPath.Clone(); if (itemToReload.GraphPathIndex != NodeIndex.Empty) { extendedPath.PushIndex(itemToReload.GraphPathIndex); } var pathToPrepend = AssetNodeMetadataCollectorBase.ConvertPath(extendedPath); foreach (var entry in itemToReload.Overrides) { var path = pathToPrepend.Append(entry.Key); overrides.Set(path, entry.Value); } } } FixupObjectReferences.RunFixupPass(asset.Key.Asset, reloaderVisitor.ObjectReferences, true, false, log); var rootNode = (IAssetNode)nodeContainer.GetNode(asset.Key.Asset); AssetPropertyGraph.ApplyOverrides(rootNode, overrides); } }