Example #1
0
        /// <summary>Restores a collection from the config node.</summary>
        /// <remarks>This method never throws.</remarks>
        /// <param name="node">The node to read the state from.</param>
        /// <param name="instance">
        /// The owner of the field. It can be <c>null</c> for the static fields.
        /// </param>
        void ReadCollectionFromConfig(ConfigNode node, object instance)
        {
            var value = fieldInfo.GetValue(instance);

            if (value == null)
            {
                // Collections are the complex objects, they must exist in order to be restored.
                DebugEx.Warning("Skip reading collection field {0}.{1} due to it's not initalized",
                                fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                return;
            }
            collectionProto.ClearItems(value);
            if (isCompound)
            {
                // For compound items read nodes and have them parsed.
                var itemCfgs = ConfigAccessor.GetNodesByPath(node, cfgPath);
                if (itemCfgs != null)
                {
                    foreach (var itemCfg in itemCfgs)
                    {
                        var itemValue = Activator.CreateInstance(collectionProto.GetItemType());
                        DeserializeCompoundFieldsFromNode(itemCfg, itemValue);
                        collectionProto.AddItem(value, itemValue);
                    }
                }
            }
            else
            {
                // For ordinary items read strings and have them parsed.
                var itemCfgs = ConfigAccessor.GetValuesByPath(node, cfgPath);
                if (itemCfgs != null)
                {
                    foreach (var itemCfg in itemCfgs)
                    {
                        try {
                            object itemValue;
                            if (isCustomSimpleType)
                            {
                                itemValue = Activator.CreateInstance(collectionProto.GetItemType());
                                ((IPersistentField)itemValue).ParseFromString(itemCfg);
                            }
                            else
                            {
                                itemValue = simpleTypeProto.ParseFromString(itemCfg, collectionProto.GetItemType());
                            }
                            collectionProto.AddItem(value, itemValue);
                        } catch (Exception ex) {
                            DebugEx.Error("Cannot parse value \"{0}\" as {1}: {2}",
                                          itemCfgs, collectionProto.GetItemType().FullName, ex.Message);
                        }
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Reads a value of an arbitrary type <typeparamref name="T"/> from the config node.
        /// </summary>
        /// <param name="node">The node to read data from.</param>
        /// <param name="pathKeys">
        /// The array of values that makes the full path. The first node in the array is the top most
        /// component of the path.
        /// </param>
        /// <param name="typeProto">
        /// A proto that can parse values of type <typeparamref name="T"/>. If not set, then
        /// <see cref="StandardOrdinaryTypesProto"/> is used.
        /// </param>
        /// <returns>The parsed value or <c>null</c> if not found.</returns>
        /// <typeparam name="T">
        /// The value type to write. The <paramref name="typeProto"/> instance must be able to handle it.
        /// </typeparam>
        /// <exception cref="ArgumentException">If type cannot be handled by the proto.</exception>
        /// <seealso cref="SetValueByPath&lt;T&gt;(ConfigNode, string[], T, KSPDev.ConfigUtils.AbstractOrdinaryValueTypeProto)"/>
        public static T?GetValueByPath <T>(
            ConfigNode node, string[] pathKeys, AbstractOrdinaryValueTypeProto typeProto = null)
            where T : struct
        {
            if (typeProto == null)
            {
                typeProto = standardTypesProto;
            }
            if (!typeProto.CanHandle(typeof(T)))
            {
                throw new ArgumentException(string.Format(
                                                "Proto {0} cannot handle type {1}", typeProto.GetType(), typeof(T)));
            }
            var strValue = ConfigAccessor.GetValueByPath(node, pathKeys);

            return(strValue == null
        ? null
        : (T?)typeProto.ParseFromString(strValue, typeof(T)));
        }
Example #3
0
        /// <summary>
        /// Reads a value of arbitrary type <typeparamref name="T"/> from a config node.
        /// </summary>
        /// <param name="node">A node to read data from.</param>
        /// <param name="pathKeys">An array of values that makes the full path. First node in the array is
        /// the top most component of the path.</param>
        /// <param name="value">A variable to read value into. The <paramref name="typeProto"/> handler
        /// must know how to convert value's type from string.</param>
        /// <param name="typeProto">A proto capable to handle the type of <paramref name="value"/>. If not
        /// set then <see cref="StandardOrdinaryTypesProto"/> is used.</param>
        /// <returns><c>true</c> if value was successfully read and stored.</returns>
        /// <typeparam name="T">The value type to read. Type proto must be able to handle it.
        /// </typeparam>
        /// <exception cref="ArgumentException">If type cannot be handled by the proto.</exception>
        public static bool GetValueByPath <T>(ConfigNode node, string[] pathKeys, ref T value,
                                              AbstractOrdinaryValueTypeProto typeProto = null)
        {
            if (typeProto == null)
            {
                typeProto = standardTypesProto;
            }
            if (!typeProto.CanHandle(typeof(T)))
            {
                throw new ArgumentException(string.Format(
                                                "Proto {0} cannot handle type {1}", typeProto.GetType(), typeof(T)));
            }
            var strValue = GetValueByPath(node, pathKeys);

            if (strValue == null)
            {
                return(false);
            }
            value = (T)typeProto.ParseFromString(strValue, typeof(T));
            return(true);
        }
Example #4
0
 /// <summary>Converts a value from config into an actual fiel's value.</summary>
 /// <param name="cfgValue">A string if value can be handled by the proto or
 /// <see cref="ConfigNode"/> if type is compound.</param>
 /// <returns>Field's value.</returns>
 internal object DeserializeValue(object cfgValue)
 {
     if (simpleTypeProto.CanHandle(valueType))
     {
         try {
             return(simpleTypeProto.ParseFromString((string)cfgValue, valueType));
         } catch (ArgumentException ex) {
             Logger.logError(string.Format(
                                 "Cannot parse value \"{0}\" as {1}: {2}", cfgValue, valueType, ex.Message));
             return(null);
         }
     }
     if (IsCompound())
     {
         var instance = Activator.CreateInstance(valueType);
         persistentField.DeserializeCompoundFieldsFromNode((ConfigNode)cfgValue, instance);
         return(instance);
     }
     Logger.logError("{0} doesn't know how to parse value type: {1}", GetType(), valueType);
     return(null);
 }
Example #5
0
        /// <summary>Reads field from a config node.</summary>
        /// <param name="node">A node to read state from.</param>
        /// <param name="instance">An owner of the field. Can be <c>null</c> for static fields.</param>
        public void ReadFromConfig(ConfigNode node, object instance)
        {
            var value = fieldInfo.GetValue(instance);

            if (collectionProto != null)
            {
                // For collection field use existing object and restore its items.
                if (value == null)
                {
                    Debug.LogWarningFormat("Skip reading collection field {0}.{1} due to it's not initalized",
                                           fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                    return;
                }
                collectionProto.ClearItems(value);
                if (isCompound)
                {
                    // For compound items read nodes and have them parsed.
                    var itemCfgs = ConfigAccessor.GetNodesByPath(node, cfgPath);
                    if (itemCfgs != null)
                    {
                        foreach (var itemCfg in itemCfgs)
                        {
                            var itemValue = Activator.CreateInstance(collectionProto.GetItemType());
                            DeserializeCompoundFieldsFromNode(itemCfg, itemValue);
                            collectionProto.AddItem(value, itemValue);
                        }
                    }
                }
                else
                {
                    // For ordinary items read strings and have them parsed.
                    var itemCfgs = ConfigAccessor.GetValuesByPath(node, cfgPath);
                    if (itemCfgs != null)
                    {
                        foreach (var itemCfg in itemCfgs)
                        {
                            try {
                                object itemValue;
                                if (isCustomSimpleType)
                                {
                                    itemValue = Activator.CreateInstance(collectionProto.GetItemType());
                                    ((IPersistentField)itemValue).ParseFromString(itemCfg);
                                }
                                else
                                {
                                    itemValue = simpleTypeProto.ParseFromString(itemCfg, collectionProto.GetItemType());
                                }
                                collectionProto.AddItem(value, itemValue);
                            } catch (Exception ex) {
                                Debug.LogErrorFormat("Cannot parse value \"{0}\" as {1}: {2}",
                                                     itemCfgs, collectionProto.GetItemType().FullName, ex.Message);
                            }
                        }
                    }
                }
            }
            else
            {
                // For ordinary field just restore value and assign it to the field.
                if (isCompound)
                {
                    if (value != null)
                    {
                        DeserializeCompoundFieldsFromNode(ConfigAccessor.GetNodeByPath(node, cfgPath), value);
                    }
                    else
                    {
                        Debug.LogWarningFormat("Skip reading compound field {0}.{1} due to it's not initalized",
                                               fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                    }
                }
                else
                {
                    var cfgValue = ConfigAccessor.GetValueByPath(node, cfgPath);
                    if (cfgValue != null)
                    {
                        try {
                            object fieldValue;
                            if (isCustomSimpleType)
                            {
                                // Prefer the existing instance of the field value when available.
                                fieldValue = value ?? Activator.CreateInstance(fieldInfo.FieldType);
                                ((IPersistentField)fieldValue).ParseFromString(cfgValue);
                            }
                            else
                            {
                                fieldValue = simpleTypeProto.ParseFromString(cfgValue, fieldInfo.FieldType);
                            }
                            fieldInfo.SetValue(instance, fieldValue);
                        } catch (Exception ex) {
                            Debug.LogErrorFormat("Cannot parse value \"{0}\" as {1}: {2}",
                                                 cfgValue, fieldInfo.FieldType.FullName, ex.Message);
                        }
                    }
                }
            }
        }