/// <summary>
        /// Restores an ordinary value collection from the config node. The type can be compound.
        /// </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 ReadOrdinaryFromConfig(ConfigNode node, object instance)
        {
            var value = fieldInfo.GetValue(instance);

            if (isCompound)
            {
                var cfgNode = ConfigAccessor.GetNodeByPath(node, cfgPath);
                if (cfgNode != null)
                {
                    if (value == null)
                    {
                        // Try creating the instance using its default constructor.
                        if (fieldInfo.IsInitOnly)
                        {
                            DebugEx.Warning(
                                "Cannot assign to a NULL readonly compound field! Field is ignored: {0}.{1}",
                                fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                            return;
                        }
                        try {
                            value = Activator.CreateInstance(fieldInfo.FieldType);
                            fieldInfo.SetValue(instance, value);
                        } catch (Exception ex) {
                            DebugEx.Error("Cannot restore field of type {0}: {1}", fieldInfo.FieldType, ex.Message);
                        }
                    }
                    DeserializeCompoundFieldsFromNode(cfgNode, value);
                }
            }
            else
            {
                if (fieldInfo.IsInitOnly)
                {
                    DebugEx.Warning("Cannot assign to a readonly field! Field is ignored: {0}.{1}",
                                    fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                    return;
                }
                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) {
                        DebugEx.Error("Cannot parse value \"{0}\" as {1}: {2}",
                                      cfgValue, fieldInfo.FieldType.FullName, ex.Message);
                    }
                }
            }
        }
        /// <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)));
        }
Exemple #3
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)
        {
            object value = null;

            if (collectionFieldHandler != null)
            {
                value = collectionFieldHandler.DeserializeValues(node);
            }
            else
            {
                var cfgData = ordinaryFieldHandler.IsCompound()
          ? ConfigAccessor.GetNodeByPath(node, cfgPath) as object
          : ConfigAccessor.GetValueByPath(node, cfgPath) as object;
                if (cfgData != null)
                {
                    value = ordinaryFieldHandler.DeserializeValue(cfgData);
                }
            }
            if (value != null)
            {
                fieldInfo.SetValue(instance, value);
            }
        }
Exemple #4
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);
                        }
                    }
                }
            }
        }