private static void Add(ISerialisableFile loadable) { if (loadable == null) { throw new ArgumentNullException("Tried to add something to the FileDatabase Data dictionary that was null"); } if (string.IsNullOrWhiteSpace(loadable.ID)) { throw new ArgumentNullException($"Loadable of type {loadable.GetType().ToString()} has missing ID field"); } Type type = loadable.GetType(); if (!Data.ContainsKey(type)) { Data.Add(type, new Dictionary <string, ISerialisableFile>()); } if (Data[type].ContainsKey(loadable.ID)) { ModDebug.LogError($"Loader already contains Type: {type.AssemblyQualifiedName} ID: {loadable.ID}, overwriting..."); Data[type][loadable.ID] = loadable; } else { Data[type].Add(loadable.ID, loadable); } }
private static void LoadFromFile(string filePath) { using (XmlReader reader = XmlReader.Create(filePath)) { string nodeData = ""; try { //Find the type name if (reader.MoveToContent() == XmlNodeType.Element) { nodeData = reader.Name; } //If we couldn't find the type name, throw an exception saying so. If the root node doesn't include the namespace, throw an exception saying so. if (string.IsNullOrWhiteSpace(nodeData)) { throw new Exception($"Could not find the root node in xml document located at {filePath}"); } TypeData data = new TypeData(nodeData); //Find the type from the root node name. The root node should be the full name of the type, including the namespace and the assembly. if (data.Type == null) { throw new Exception($"Unable to find type {data.FullName}"); } XmlRootAttribute root = new XmlRootAttribute(); root.ElementName = nodeData; root.IsNullable = true; XmlSerializer serialiser = new XmlSerializer(data.Type, root); ISerialisableFile loaded = (ISerialisableFile)serialiser.Deserialize(reader); if (loaded != null) { Add(loaded); } else { throw new Exception($"Unable to load {data.FullName} from file {filePath}."); } } catch (Exception ex) { if (ex is ArgumentNullException && ((ArgumentNullException)ex).ParamName == "type") { throw new Exception($"Cannot get a type from type name {nodeData} in file {filePath}", ex); } throw new Exception($"An error occurred whilst loading file {filePath}", ex); } } }
/// <summary> /// Saves the given object instance which inherits ISerialisableFile to an xml file. /// </summary> /// <param name="moduleName">The folder name of the module to save to.</param> /// <param name="sf">Instance of the object to save to file.</param> /// <param name="location">Indicates whether to save the file to the ModuleData/Loadables folder or to the mod's Config folder in Bannerlord's 'My Documents' directory.</param> public static bool SaveToFile(string moduleName, ISerialisableFile sf, Location location = Location.Modules) { try { if (string.IsNullOrWhiteSpace(sf.ID)) { throw new Exception($"FileDatabase tried to save an object of type {sf.GetType().FullName} but the ID value was null."); } if (string.IsNullOrWhiteSpace(moduleName)) { throw new Exception($"FileDatabase tried to save an object of type {sf.GetType().FullName} with ID {sf.ID} but the module folder name given was null or empty."); } //Gets the intended path for the file. string path = GetPathForModule(moduleName, location); if (location == Location.Modules && !Directory.Exists(path)) { throw new Exception($"FileDatabase cannot find the module named {moduleName}"); } else if (location == Location.Configs && !Directory.Exists(path)) { Directory.CreateDirectory(path); } if (location == Location.Modules) { path = Path.Combine(path, "ModuleData", LoadablesFolderName); } if (sf is ISubFolder) { ISubFolder subFolder = sf as ISubFolder; if (!string.IsNullOrWhiteSpace(subFolder.SubFolder)) { path = Path.Combine(path, subFolder.SubFolder); } } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path = Path.Combine(path, GetFileNameFor(sf)); if (File.Exists(path)) { File.Delete(path); } using (XmlWriter writer = XmlWriter.Create(path, new XmlWriterSettings() { Indent = true, OmitXmlDeclaration = true })) { XmlRootAttribute rootNode = new XmlRootAttribute(); rootNode.ElementName = $"{sf.GetType().Assembly.GetName().Name}-{sf.GetType().FullName}"; XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }); var serializer = new XmlSerializer(sf.GetType(), rootNode); serializer.Serialize(writer, sf, xmlns); } return(true); } catch (Exception ex) { ModDebug.ShowError($"Cannot create the file for type {sf.GetType().FullName} with ID {sf.ID} for module {moduleName}:", "Error saving to file", ex); return(false); } }
/// <summary> /// Returns the file name for the given ISerialisableFile /// </summary> /// <param name="sf">The instance of the ISerialisableFile to retrieve the file name for.</param> /// <returns>Returns the file name of the given ISerialisableFile, including the file extension.</returns> public static string GetFileNameFor(ISerialisableFile sf) { return($"{sf.GetType().Name}.{sf.ID}.xml"); }