/// <summary>
        /// Saves configuration data from the specified configuration into the backend storage.
        /// </summary>
        /// <param name="configuration">Configuration to save.</param>
        /// <param name="flags">Flags controlling the saving behavior.</param>
        /// <exception cref="ConfigurationException">
        /// The configuration is a child configuration (try to load the root configuration instead).
        /// </exception>
        public override void Save(CascadedConfiguration configuration, CascadedConfigurationSaveFlags flags)
        {
            if (mConfigurationFilePath == null)
            {
                throw new ConfigurationException("The configuration is a child configuration (try to save the root configuration instead).");
            }

            // load existing configuration file
            XmlDocument doc = new XmlDocument();

            try
            {
                if (File.Exists(mConfigurationFilePath))
                {
                    doc.Load(mConfigurationFilePath);
                }
            }
            catch (Exception ex)
            {
                throw new ConfigurationException(
                          string.Format("Loading existing configuration file ({0}) before saving failed.", mConfigurationFilePath),
                          ex);
            }

            // create root node, if necessary
            XmlElement root = doc.SelectSingleNode("//ConfigurationFile") as XmlElement;

            if (root == null)
            {
                root = doc.CreateElement("ConfigurationFile");
                doc.AppendChild(root);
            }

            // modify the xml document to reflect the settings in the configuration
            lock (configuration.Sync) {
                SaveInternal(configuration, root, flags);
            }

            // save the xml document
            string directoryPath = Path.GetDirectoryName(mConfigurationFilePath);

            if (!string.IsNullOrWhiteSpace(directoryPath) && !Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            string tempFile = mConfigurationFilePath + ".tmp";

            doc.Save(tempFile);
            try { File.Delete(mConfigurationFilePath); } catch { }
            File.Move(tempFile, mConfigurationFilePath);
        }
        /// <summary>
        /// Writes the specified configuration into the specified XML element
        /// </summary>
        /// <param name="configuration">Configuration to write.</param>
        /// <param name="parent">Parent element in the XML tree.</param>
        /// <param name="flags">Flags controlling the saving behavior.</param>
        private void SaveInternal(CascadedConfiguration configuration, XmlElement parent, CascadedConfigurationSaveFlags flags)
        {
            // create 'Configuration' element
            XmlElement configurationElement = parent.SelectSingleNode(string.Format("Configuration[@name='{0}']", configuration.Name)) as XmlElement;

            if (configurationElement == null)
            {
                configurationElement = parent.OwnerDocument.CreateElement("Configuration");
                XmlAttribute configurationNameAttribute = parent.OwnerDocument.CreateAttribute("name");
                configurationNameAttribute.InnerText = configuration.Name;
                configurationElement.Attributes.Append(configurationNameAttribute);
                parent.AppendChild(configurationElement);
            }

            foreach (ICascadedConfigurationItem item in configuration.Items)
            {
                if (item.HasValue || flags.HasFlag(CascadedConfigurationSaveFlags.SaveInheritedSettings))
                {
                    XmlElement itemElement = SetItem(configurationElement, configuration, item.Name, item.Type, item.Value);

                    // remove all comment nodes before the node
                    for (int i = 0; i < configurationElement.ChildNodes.Count; i++)
                    {
                        XmlNode node = configurationElement.ChildNodes[i];
                        if (node == itemElement)
                        {
                            for (int j = i; j > 0; j--)
                            {
                                node = configurationElement.ChildNodes[j - 1];
                                if (node.NodeType != XmlNodeType.Comment)
                                {
                                    break;
                                }
                                configurationElement.RemoveChild(node);
                            }
                            break;
                        }
                    }

                    // add comment nodes
                    if (item.Comment != null)
                    {
                        string[] commentLines = item.Comment.Split('\n');
                        foreach (string commentLine in commentLines)
                        {
                            string line = commentLine.Trim();
                            if (line.Length > 0)
                            {
                                XmlComment commentNode = configurationElement.OwnerDocument.CreateComment(line);
                                configurationElement.InsertBefore(commentNode, itemElement);
                            }
                        }
                    }
                }
                else
                {
                    RemoveItem(configurationElement, item.Name);
                }
            }

            // save child configurations
            foreach (CascadedConfiguration child in configuration.Children)
            {
                SaveInternal(child, configurationElement, flags);
            }
        }
Example #3
0
        /// <summary>
        /// Saves the specified configuration in the registry.
        /// </summary>
        /// <param name="configuration">Configuration to save.</param>
        /// <param name="flags">Flags controlling the save behavior.</param>
        /// <exception cref="SecurityException">The user does not have the permissions required to read from the registry key.</exception>
        /// <exception cref="ConfigurationException">Saving the configuration failed due to a serialization error.</exception>
        public override void Save(CascadedConfiguration configuration, CascadedConfigurationSaveFlags flags)
        {
            lock (configuration.Sync)
            {
                string keyPath = mKeyBasePath + "\\" + configuration.Path.Trim('/').Replace('/', '\\');

                foreach (ICascadedConfigurationItem item in configuration.Items)
                {
                    if (item.HasValue || flags.HasFlag(CascadedConfigurationSaveFlags.SaveInheritedSettings))
                    {
                        if (item.Type.IsArray)
                        {
                            // array type => always mapped to a multi-string
                            // => use converter to perform the conversion (all basically supported types also have a converter)
                            Type       elementType = item.Type.GetElementType();
                            IConverter converter   = GetValueConverter(elementType);
                            if (converter == null)
                            {
                                converter = Converters.GetGlobalConverter(elementType);
                            }

                            List <string> value = new List <string>();
                            foreach (object obj in (IEnumerable)item.Value)
                            {
                                value.Add(converter.ConvertObjectToString(obj, CultureInfo.InvariantCulture));
                            }

                            Registry.SetValue(keyPath, item.Name, value.ToArray(), RegistryValueKind.MultiString);
                        }
                        else
                        {
                            if (item.Type == typeof(bool) || item.Type == typeof(byte) || item.Type == typeof(ushort) || item.Type == typeof(uint))
                            {
                                // booleans and unsigned integers (8/16/32-bit) best map to a registry DWORD (32-bit)
                                object value = item.Value;
                                if (value is bool)
                                {
                                    value = (bool)value ? 1 : 0;
                                }
                                Registry.SetValue(keyPath, item.Name, value, RegistryValueKind.DWord);
                            }
                            else if (item.Type == typeof(ulong))
                            {
                                // unsigned integer (64-bit) best maps to a registry DWORD (64-bit)
                                Registry.SetValue(keyPath, item.Name, item.Value, RegistryValueKind.QWord);
                            }
                            else if (item.Type == typeof(string[]))
                            {
                                // a string hash becomes a registry multi-string
                                Registry.SetValue(keyPath, item.Name, item.Value, RegistryValueKind.MultiString);
                            }
                            else if (item.Type.IsEnum)
                            {
                                // an enumeration value should be stored as a string
                                string value = item.Value.ToString();
                                Registry.SetValue(keyPath, item.Name, value, RegistryValueKind.String);
                            }
                            else
                            {
                                // the configuration item contains a value that is not covered by the standard types
                                // => try to find some other way to make it persistent...
                                if (SaveUsingConverter(item, keyPath))
                                {
                                    continue;
                                }

                                // there is no way to make the configuration item persistent
                                // (should never happen, since types that are not supported should never get into the configuration)
                                throw new ConfigurationException(
                                          "The configuration contains an item (path: {0}, type: {1}) that cannot be loaded/saved.",
                                          item.Path, item.Type.FullName);
                            }
                        }
                    }
                    else
                    {
                        // the configuration item does not have a value
                        // => remove corresponding registry value
                        DeleteRegistryValue(keyPath, item.Name);
                    }
                }
            }

            // save child configurations
            foreach (CascadedConfiguration child in configuration.Children)
            {
                child.Save(flags);
            }
        }
 /// <summary>
 /// Saves configuration data from the specified configuration into the backend storage.
 /// </summary>
 /// <param name="configuration">Configuration to save.</param>
 /// <param name="flags">Flags controlling the saving behavior.</param>
 public abstract void Save(CascadedConfiguration configuration, CascadedConfigurationSaveFlags flags);