예제 #1
0
        public void Load(params string[] storageCapsuleIDs)
        {
            using (ActiveRefHandler = new SaveableReferenceIdHandler())
            {
                RefreshCachedData(storageCapsuleIDs);

                foreach (var capsuleToStorage in _cachedStorageCapsules)
                {
                    if (storageCapsuleIDs != null && storageCapsuleIDs.Length > 0 && Array.IndexOf(storageCapsuleIDs, capsuleToStorage.Key.ID) < 0)
                    {
                        continue;
                    }

                    List <ISaveable> _allLoadedReferences   = new List <ISaveable>();
                    List <string>    _allLoadedReferenceIds = new List <string>();

                    Action <string> referenceRequestedEventAction = (id) =>
                    {
                        if (_allLoadedReferenceIds.Contains(id))
                        {
                            return;
                        }

                        _allLoadedReferenceIds.Add(id);

                        if (!capsuleToStorage.Value.TryGetValue(id, out StorageDictionary storage))
                        {
                            storage = new StorageDictionary(capsuleToStorage.Key.ID, this);
                        }

                        if (id == ROOT_SAVE_DATA_CAPSULE_REFERENCE_ID)
                        {
                            capsuleToStorage.Key.Load(storage);
                            _allLoadedReferences.Add(capsuleToStorage.Key);
                        }
                        else if (storage.LoadValue(STORAGE_REFERENCE_TYPE_ID_ULONG_KEY, out ulong classTypeId))
                        {
                            ISaveable referenceInstance = _storageObjectFactory.LoadSaveableObject(classTypeId, storage);
                            ActiveRefHandler.SetReferenceReady(referenceInstance, id);
                            _allLoadedReferences.Add(referenceInstance);
                        }
                        else if (storage.LoadValue(STORAGE_REFERENCE_TYPE_STRING_KEY, out string classTypeFullName))
                        {
                            Type      referenceType       = Type.GetType(classTypeFullName);
                            bool      methodLoadInterface = typeof(ISaveableLoad).IsAssignableFrom(referenceType);
                            ISaveable referenceInstance   = (methodLoadInterface ? Activator.CreateInstance(referenceType) : Activator.CreateInstance(referenceType, storage)) as ISaveable;
                            ActiveRefHandler.SetReferenceReady(referenceInstance, id);

                            if (methodLoadInterface)
                            {
                                ((ISaveableLoad)referenceInstance).Load(storage);
                            }

                            _allLoadedReferences.Add(referenceInstance);
                        }
                        else
                        {
                            Debug.LogErrorFormat("UNABLE TO LOAD REFERENCE ID {0}'s CLASS TYPE NAME", id);
                        }
                    };

                    ActiveRefHandler.ReferenceRequestedEvent += referenceRequestedEventAction;
                    referenceRequestedEventAction(ROOT_SAVE_DATA_CAPSULE_REFERENCE_ID);
                    ActiveRefHandler.LoadRemainingAsNull();
                    ActiveRefHandler.ReferenceRequestedEvent -= referenceRequestedEventAction;

                    for (int i = _allLoadedReferences.Count - 1; i >= 0; i--)
                    {
                        _allLoadedReferences[i].LoadingCompleted();
                    }

                    _allLoadedReferences   = null;
                    _allLoadedReferenceIds = null;
                }
            }
        }
예제 #2
0
        public void Save(bool flushAfterSave, params string[] storageCapsuleIDs)
        {
            Dictionary <IStorageCapsule, Dictionary <string, StorageDictionary> > buffer   = new Dictionary <IStorageCapsule, Dictionary <string, StorageDictionary> >();
            Dictionary <string, IStorageCapsule> _alreadySavedReferencesToOriginCapsuleMap = new Dictionary <string, IStorageCapsule>();

            using (ActiveRefHandler = new SaveableReferenceIdHandler())
            {
                foreach (var pair in _cachedStorageCapsules)
                {
                    if (storageCapsuleIDs != null && storageCapsuleIDs.Length > 0 && Array.IndexOf(storageCapsuleIDs, pair.Key.ID) < 0)
                    {
                        continue;
                    }

                    Dictionary <string, StorageDictionary> referencesSaved = new Dictionary <string, StorageDictionary>();

                    Action <string, ISaveable> refDetectedAction = (refID, referenceInstance) =>
                    {
                        if (_alreadySavedReferencesToOriginCapsuleMap.TryGetValue(refID, out IStorageCapsule holdingCapsule))
                        {
                            if (holdingCapsule != pair.Key)
                            {
                                throw new Exception(string.Format("Save aborted! Reference {0} saved in capsule {1} while capsule {2} is saving it now! Each capsule should not be saving cross references!", referenceInstance.ToString(), holdingCapsule.ID, pair.Key.ID));
                            }
                        }

                        if (!referencesSaved.ContainsKey(refID))
                        {
                            StorageDictionary storageDictForRef = new StorageDictionary(pair.Key.ID, this);
                            referencesSaved.Add(refID, storageDictForRef);
                            storageDictForRef.SaveValue(STORAGE_REFERENCE_TYPE_STRING_KEY, referenceInstance.GetType().AssemblyQualifiedName);
                            storageDictForRef.SaveValue(STORAGE_REFERENCE_TYPE_ID_ULONG_KEY, _storageObjectFactory.GetIdForSaveable(referenceInstance.GetType()));
                            referenceInstance.Save(storageDictForRef);

                            if (pair.Value.TryGetValue(refID, out StorageDictionary oldData))
                            {
                                foreach (var valueKey in oldData.GetValueStorageKeys())
                                {
                                    if (oldData.ShouldKeepValueKey(valueKey) && !storageDictForRef.HasValueKey(valueKey))
                                    {
                                        storageDictForRef.SetValue(valueKey, oldData.GetValueSection(valueKey).GetValue());
                                    }
                                }

                                foreach (var refKey in oldData.GetRefStorageKeys())
                                {
                                    if (oldData.ShouldKeepRefKey(refKey) && !storageDictForRef.HasRefKey(refKey))
                                    {
                                        storageDictForRef.SetValueRef(refKey, oldData.GetValueRef(refKey));
                                    }
                                }
                            }

                            if (refID != ROOT_SAVE_DATA_CAPSULE_REFERENCE_ID)
                            {
                                _alreadySavedReferencesToOriginCapsuleMap.Add(refID, pair.Key);
                            }
                        }
                    };

                    ActiveRefHandler.IdForReferenceRequestedEvent += refDetectedAction;
                    refDetectedAction(ROOT_SAVE_DATA_CAPSULE_REFERENCE_ID, pair.Key);
                    ActiveRefHandler.IdForReferenceRequestedEvent -= refDetectedAction;

                    buffer.Add(pair.Key, referencesSaved);
                }
            }

            foreach (var pair in buffer)
            {
                _cachedStorageCapsules[pair.Key] = pair.Value;
            }

            if (flushAfterSave)
            {
                Flush();
            }
        }