private static async Task NewEveryTimeMethod(string jsonString, ProgramSaveFiles saveFile) { StorageFile localFile = await ApplicationData.Current.LocalFolder.CreateFileAsync( saveFile.ToString() + ".dat", CreationCollisionOption.ReplaceExisting); await FileIO.WriteTextAsync(localFile, jsonString); }
//Saving. /// <summary> /// A static method for saving a object asynchronously as a JSON file. The object can be of any kind, including lists of objects. /// </summary> /// <param name="objectToSave">The object that is saved. Examples could include, int list<int>, string etc.</param> /// <param name="saveFile">The name of the save file. Currently this is restricted to an enumerator type to reduce risk. /// If you want to save to a new file, you should first add another value to the ProgramSaveFile enum under PersistencyFacade. </param> /// <param name="saveMode"> NewEveryTime: Each time the method is used to save to a file, that file is overwritten with the new content, if it already exist. /// Continuous: If the save file already exist the new content is added to file instead of overwriting it. /// You should only continuously save the same kind of data so that loading it is easy. Example, if you save an int, don't save a string to the same file, or a list of ints.'</param> /// <returns>Task</returns> public static async Task SaveObjectsAsync(object objectToSave, ProgramSaveFiles saveFile, SaveMode saveMode) { string jsonString = ""; jsonString = await Task.Run(() => JsonConvertMethod(objectToSave)); await SerializeFiles(jsonString, saveFile, saveMode); }
private static async Task SaveIndexContinuousHelper(string jsonString, ProgramSaveFiles saveFile) { string jsonStringLength = jsonString.Length.ToString(); jsonStringLength = jsonStringLength + ";"; string saveFileIndex = saveFile.ToString() + fileIndex; await WriteToFileContinuousHelper(jsonStringLength, saveFileIndex); }
private static async Task SerializeFiles(string jsonString, ProgramSaveFiles saveFile, SaveMode saveMode) { try { switch (saveMode) { case SaveMode.NewEveryTime: await NewEveryTimeMethod(jsonString, saveFile); break; case SaveMode.Continuous: await ContinuousMethod(jsonString, saveFile); break; } } catch (IOException iox) { //Implement Exception. MessageDialogHelper.Show("There was a problem accessing your files:\n" + iox.Message, "File In/Out Exception"); } }
//Loading. public static async Task <object> LoadCollectionWithPolymorphism(ProgramSaveFiles saveFile, Type mainCollectionType, Type[] subCollectionTypes) { StorageFile localFile = null; try { localFile = await ApplicationData.Current.LocalFolder.GetFileAsync(saveFile.ToString() + ".dat"); } catch (FileNotFoundException fnfx) { throw new FileNotSavedException("It appears no save file with this name exist. Are you sure you have saved any data yet? File:" + fnfx.FileName, fnfx); } string saveData = await FileIO.ReadTextAsync(localFile); List <string> seperatedMetaData = SeperateMetaData(saveData); //Order: type data, elementsLength data, pureData(the collection itself). string pureData = seperatedMetaData[2]; //BreakPoint. List <Type> collectionElementTypes = new List <Type>(); List <int> collectionElementsLength = new List <int>(); List <Task> loadMetaDataListsTask = new List <Task>(); loadMetaDataListsTask.Add(Task.Run(() => { collectionElementTypes = JsonConvert.DeserializeObject(seperatedMetaData[0], typeof(List <Type>)) as List <Type>; })); loadMetaDataListsTask.Add(Task.Run(() => { collectionElementsLength = JsonConvert.DeserializeObject(seperatedMetaData[1], typeof(List <int>)) as List <int>; })); await Task.WhenAll(loadMetaDataListsTask); List <int> combinedElementsLength = new List <int>(); combinedElementsLength.Add(collectionElementsLength[0]); List <int> TypesKeys = new List <int>() { 0 }; int listIndex = 0; for (int i = 1; i < collectionElementTypes.Count; i++) { if (collectionElementTypes[i] == collectionElementTypes[i - 1]) { combinedElementsLength[listIndex] += collectionElementsLength[i] + 1; } else { TypesKeys.Add(i); combinedElementsLength.Add(collectionElementsLength[i]); listIndex++; } } string pureDataOpeningCharacter = pureData.Substring(0, 1); //Break point. pureData = pureData.Remove(0, 1); string pureDataClosingCharacter = pureData.Substring(pureData.Length - 1, 1); //pureData is now open. Dictionary <Type, string> typeSeparatedDataStrings = new Dictionary <Type, string>(); //typeSeparatedDataStrings.Add(collectionElementTypes[uniqueTypesKeys[0]],pureData.Substring(0,combinedElementsLength[0])); //pureData = pureData.Remove(0, combinedElementsLength[0]); int index = 0; foreach (int typeKey in TypesKeys) //Break point. { if (typeSeparatedDataStrings.ContainsKey(collectionElementTypes[typeKey])) { typeSeparatedDataStrings[collectionElementTypes[typeKey]] += "," + pureData.Substring(0, combinedElementsLength[index]); pureData = pureData.Remove(0, combinedElementsLength[index] + 1); } else { typeSeparatedDataStrings.Add(collectionElementTypes[typeKey], pureData.Substring(0, combinedElementsLength[index])); pureData = pureData.Remove(0, combinedElementsLength[index] + 1); } index++; } List <object> deserializedSubCollections = new List <object>(); //Break point. object mainCollection = null; List <Type> subCollectionParamTypes = new List <Type>(); await Task.Run(() => { foreach (Type subCollectionType in subCollectionTypes) { Type actualType = GetGenericParamFromCollection(subCollectionType); if (typeSeparatedDataStrings.ContainsKey(actualType)) { subCollectionParamTypes.Add(actualType); string subCollectionDataString = pureDataOpeningCharacter + typeSeparatedDataStrings[actualType] + pureDataClosingCharacter; deserializedSubCollections.Add(JsonConvert.DeserializeObject(subCollectionDataString, subCollectionType)); } } string mainCollectionString = pureDataOpeningCharacter + pureDataClosingCharacter; mainCollection = JsonConvert.DeserializeObject(mainCollectionString, mainCollectionType); }); mainCollection = await AddToMainCollection(mainCollection, deserializedSubCollections, TypesKeys, collectionElementTypes, subCollectionParamTypes); return(mainCollection); //;D //Dictionary<Type,List<int>> typeSeperatedDictionary = new Dictionary<Type, List<int>>(); //typeSeperatedDictionary.Add(collectionElementTypes[0],new List<int>(){collectionElementslength[0]}); //int listCount = 0; //for (int i = 1; i < collectionElementTypes.Count; i++) //{ // if (collectionElementTypes[i]==collectionElementTypes[i-1]) // { // typeSeperatedDictionary[collectionElementTypes[i]][listCount] += collectionElementslength[i];//Method that does this, then starts a new method like this for new types? Then have them jump back and forth. // } //} } //Break point.
//New Methods. //Saving. public static async Task SaveCollectionWithPolymorphism(object collectionToSave, ProgramSaveFiles saveFile) { Type collectionType = collectionToSave.GetType(); string collectionNameSpace = collectionType.Namespace; if (collectionNameSpace == "System.Collections.Generic" || collectionNameSpace == "System.Collections.ObjectModel") { bool containsKeyValuePairs = collectionType.GetProperty("Keys") != null; PropertyInfo countInfo = collectionType.GetProperty("Count"); Nullable <int> collectionCount = countInfo.GetValue(collectionToSave) as Nullable <int>; if (collectionCount <= 0 || collectionCount == null) { throw new CollectionTooSmallException("Please only save a collection with at least one element"); } MethodInfo getEnumeratorInfo = collectionType.GetMethod("GetEnumerator"); object collectionEnum = getEnumeratorInfo.Invoke(collectionToSave, null); List <object> results = await DisectCollectionEnum(collectionEnum, containsKeyValuePairs, collectionCount); List <Type> elementTypes = results[0] as List <Type>; List <int> elementsLength = results[1] as List <int>; //Tested with list and dictionary to this point and found it working as intended. string metaData = await PrepareMetaData(elementTypes, elementsLength); //NewEveryTimeImplementation StorageFile localFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(saveFile.ToString() + ".dat", CreationCollisionOption.ReplaceExisting); string saveData = ""; await Task.Run(() => { saveData = metaData + JsonConvert.SerializeObject(collectionToSave); }); await FileIO.WriteTextAsync(localFile, saveData); } else { throw new WrongOrUnsupportedTypeException("Unsupported type. The implementation of this method doesn't support the collection type it received. If it is indeed a collection contact the developer, lol"); } }
//Loading. /// <summary> /// A static method for asynchronously loading objects from a JSON file. This includes just a singular object. /// </summary> /// <param name="saveFile">The save file that will be loaded.</param> /// <param name="objectType">The type of object that should be loaded. If using continuous mode to save, the "outer" type should always be of type List, /// even if saving a List. /// Example, if saving a Ticket object continuously, objectType is List<Ticket>, if saving a List<Ticket> continuously, objectType is List<List<Ticket>> /// Use the "typeof" keyword to get the type.</param> /// <returns>Object. If continuous mode was used to save, the returned object will always be a list. Use typecast declare what kind of list is returned. /// Example, if loading Ticket object(s) continuously typecast the return value of the method to (List<Ticket>)</returns> public static async Task <object> LoadObjectsAsync(ProgramSaveFiles saveFile, Type objectType) { StorageFile localFile = null; StorageFile localFileIndex = null; List <int> savedElementsLengthList = null; try { string filePathNormal = saveFile.ToString() + ".dat"; localFile = await GetStorageFile(filePathNormal); } catch (FileNotFoundException fnfx) { //MessageDialogHelper.Show("Your save file could not be found, have you forgot to save any data to it?\n" + fnfx.Message, "File not Found Exception"); //return null; throw new FileNotSavedException("Your save file could not be found, have you forgot to save any data to it ?\n", fnfx); } try { string filePathIndex = saveFile.ToString() + fileIndex + ".dat"; localFileIndex = await GetStorageFile(filePathIndex); savedElementsLengthList = await LoadIndexFile(localFileIndex); } catch (FileNotFoundException fnfx) { object loadedObject = await LoadNormalFile(localFile, objectType); return(loadedObject); } string jsonString = await FileIO.ReadTextAsync(localFile); object loadedObjects = null; StringBuilder loadedJsonObjectsAsList = new StringBuilder("["); try { await Task.Run(() => { foreach (int ElementLength in savedElementsLengthList) { string jsonObjectString = jsonString.Substring(0, ElementLength); jsonString = jsonString.Remove(0, ElementLength); if (jsonString.Length > 0) { loadedJsonObjectsAsList.Append(jsonObjectString + ","); } else { loadedJsonObjectsAsList.Append(jsonObjectString); } } loadedJsonObjectsAsList.Append(']'); loadedObjects = JsonConvert.DeserializeObject(loadedJsonObjectsAsList.ToString(), objectType); }); } catch (Exception e) { throw; //Implement possible exceptions, one would be if a user used both SaveModes with the same file. The file and the indexfile would conflict, this error should probably just tell the user to only use one SaveMethod, as using both for the same file makes no sense. } return(loadedObjects); }
private static async Task ContinuousMethod(string jsonString, ProgramSaveFiles saveFile) { await SaveIndexContinuousHelper(jsonString, saveFile); await WriteToFileContinuousHelper(jsonString, saveFile.ToString()); }