/// <summary> /// Save given data to configuration file. /// </summary> /// <typeparam name="T">The type of the data that has to be saved.</typeparam> /// <param name="sectionData">The data that has to be saved in the configuration file.</param> public static void SaveSection <T>(T sectionData) where T : class { s_CfgMutex.WaitOne(); foreach (IConfigSource source in s_Sources.Where(s => !s.IsReadOnly)) { XmlSerializer xs = new XmlSerializer(typeof(T)); //use a memory stream to holt temporary output in order to be able to modify sections in the middle of the file. using (MemoryStream ms = new MemoryStream()) { Stream dataStream = source.Open(); using (XmlReader xr = XmlReader.Create(dataStream, s_ReaderSettings)) { using (XmlWriter xw = XmlWriter.Create(ms, s_WriterSettings)) { //states need to be maually changed otherwise XmlSerializer try to write start document node //that for Fragment xml throw an exception. xw.FakeWrite(); //flag to indicate if the section already exists bool dataWritten = false; xr.MoveToContent(); //check if file is empty if (xr.NodeType != XmlNodeType.None) { //loop over all available sections while (xr.NodeType == XmlNodeType.Element) { if (xr.Name != GetSectionName <T>()) { //if not requested section copy it to output xw.WriteNode(xr.ReadSubtree(), false); } else { xs.Serialize(xw, sectionData, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })); dataWritten = true; } //move to next section xr.Skip(); } } if (!dataWritten) { //section has not been found, create it xs.Serialize(xw, sectionData, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })); } } } //update the settings file with the data stored in the temporary memory stream dataStream.Seek(0, SeekOrigin.Begin); dataStream.SetLength(0); dataStream.Write(ms.GetBuffer(), 0, (int)ms.Length); source.Close(); } } s_CfgMutex.ReleaseMutex(); }