using System.Collections.Generic;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
[XmlType("StoredMessage")]
public class StoredMessage
public string From { get; set; }
public string Date { get; set; }
public string Message { get; set; }
[XmlRoot("MessageHistory")]
public class MessageHistory : List<StoredMessage>
class ErrorLogger : IDisposable
private string xmlPath = "Messages.Xml";
private object objLock = new Object();
public string ErrorMessage { get; set; }
const string rootName = "MessageHistory";
static readonly XmlSerializer serializer = new XmlSerializer(typeof(StoredMessage), new XmlRootAttribute(rootName));
public MessageHistory Operation(string from, string message, FileAccess access)
var list = new MessageHistory();
using (var file = File.Open(xmlPath, FileMode.OpenOrCreate))
list.AddRange(XmlSerializerHelper.ReadObjects<StoredMessage>(file, false, serializer));
if (list.Count == 0 && String.IsNullOrEmpty(message))
message = "Created File";
var item = new StoredMessage()
Date = DateTime.Now.ToString("s"),
if ((access == FileAccess.ReadWrite) || (access == FileAccess.Write))
file.Seek(0, SeekOrigin.End);
var writerSettings = new XmlWriterSettings
OmitXmlDeclaration = true,
using (var textWriter = new StreamWriter(file))
using (var xmlWriter = XmlWriter.Create(textWriter, writerSettings))
serializer.Serialize(xmlWriter, item);
var sb = new StringBuilder();
sb.AppendLine(String.Format("Top Level Error: <b>{0}</b>", error.Message));
var err = error.InnerException;
sb.AppendLine(String.Format("\tInner {0}: {1}", index, err.Message));
err = err.InnerException;
ErrorMessage = sb.ToString();
if (xmlPath != null && File.Exists(xmlPath))
return File.ReadAllText(xmlPath);
#region IDisposable Members
var xmlPath = Interlocked.Exchange(ref this.xmlPath, null);
if (xmlPath != null && File.Exists(xmlPath))
public partial class XmlSerializerHelper
public static List<T> ReadObjects<T>(Stream stream, bool closeInput = true, XmlSerializer serializer = null)
var list = new List<T>();
serializer = serializer ?? new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings
ConformanceLevel = ConformanceLevel.Fragment,
using (var xmlTextReader = XmlReader.Create(stream, settings))
while (xmlTextReader.Read())
if (xmlTextReader.NodeType == XmlNodeType.Element)
using (var subReader = xmlTextReader.ReadSubtree())
var logEvent = (T)serializer.Deserialize(subReader);
public static void Test()
using (var logger = new ErrorLogger())
List<MessageHistory> lists = new List<MessageHistory>();
foreach (var message in messages)
var list = logger.Operation("test class", message, FileAccess.ReadWrite);
Assert.IsTrue(list.Last().Message == message);
Assert.IsTrue(lists.Count == messages.Length && lists.Last().Select(i => i.Message).SequenceEqual(messages));
Console.WriteLine("Final XML: ");
Console.WriteLine(logger.GetXml());
Console.WriteLine("\nFinal list of messages in memory: ");
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(lists.Last(), Newtonsoft.Json.Formatting.Indented));
Console.WriteLine("\nDone.");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);