public void Serialize(Stream stream, IUnique source, AlertLog log = null) { log?.RaiseAlert("BEG", "Beginning serialisation..."); _Format = new Dictionary <string, TypeFieldsFormat>(); _Aliases = new Dictionary <Type, string>(); _Uniques = new UniquesCollection(); _Writer = new StreamWriter(stream); // Write base item: _Writer.WriteLine(SerializeItem(source)); // Write uniques: int i = 0; while (i < _Uniques.Count) { log?.RaiseAlert("PROG", "Writing...", (double)i / (double)_Uniques.Count, AlertLevel.Information); IUnique unique = _Uniques[i]; _Writer.WriteLine(SerializeItem(unique)); i++; } //_Writer.WriteLine(); //_Writer.WriteLine(FORMAT); //_Writer.Write(GenerateFormatDescription()); _Writer.Flush(); log?.RaiseAlert("BEG", "Serialisation complete."); }
public IUnique Deserialize(Stream stream, AlertLog log = null) { IUnique result = null; _Format = new Dictionary <string, TypeFieldsFormat>(); _Aliases = new Dictionary <Type, string>(); _Uniques = new UniquesCollection(); _Reader = new StreamReader(stream); // First, read through once to end: log?.RaiseAlert("FORM", "Reading format data..."); string line; int lineCount = 0; while ((line = _Reader.ReadLine()) != null) { lineCount++; if (line.StartsWith(FORMAT)) { ReadFormat(line, log); } else if (line.StartsWith(DATA)) { // Initial pass: Create object int i = DATA.Length; string guid = line.NextChunk(ref i, KEY_SEPARATOR); string typeAlias = line.NextChunk(ref i, OPEN_DATABLOCK); if (_Format.ContainsKey(typeAlias)) { TypeFieldsFormat format = _Format[typeAlias]; IUnique unique = format.Type.Instantiate() as IUnique;//FormatterServices.GetUninitializedObject(format.Type) as IUnique; if (unique is IUniqueWithModifiableGUID) { var uniqueMG = (IUniqueWithModifiableGUID)unique; uniqueMG.SetGUID(new Guid(guid)); } else { FieldInfo fI = format.Type.GetBaseField("_GUID"); // Will not work if backing field is named differently! fI.SetValue(unique, new Guid(guid)); } _Uniques.Add(unique); if (result == null) { result = unique; // Set primary output object } } else { log?.RaiseAlert("FNF" + typeAlias, "Formatting data for type alias '" + typeAlias + "' not found.", AlertLevel.Warning); } } } log?.RaiseAlert("FORM", "Format data read."); // Next: Second pass - populate fields with data // Rewind: stream.Seek(0, SeekOrigin.Begin); _Reader = new StreamReader(stream); int lineNum = 0; while ((line = _Reader.ReadLine()) != null) { log?.RaiseAlert("DAT", "Reading data...", (double)lineNum / (double)lineCount); if (line.StartsWith(DATA)) { // Initial pass: Create object int i = DATA.Length; string guid = line.NextChunk(ref i, KEY_SEPARATOR); string typeAlias = line.NextChunk(ref i, OPEN_DATABLOCK); if (_Format.ContainsKey(typeAlias)) { TypeFieldsFormat format = _Format[typeAlias]; object unique = _Uniques[new Guid(guid)]; PopulateFields(ref unique, format, ref i, line, log); } } lineNum++; } log?.RaiseAlert("DAT", "Reading data complete.", 1.0); log?.RaiseAlert("FIN", "Finalising..."); // Finally: Call OnDeserialized function on each object foreach (var unique in _Uniques) { MethodInfo mInfo = unique.GetType().GetOnDeserializedMethod(); if (mInfo != null) { mInfo.Invoke(unique, new object[] { new StreamingContext() }); } // TODO: Pass in populated streamingcontext arguments? } log?.RaiseAlert("FIN", "Finalised"); return(result); }