示例#1
0
            /// <summary>
            /// Deserializes the specified object from a ConfigNode, restoring non-static fields and properties with
            /// getters and setters
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="node"></param>
            /// <param name="typeFormatter"></param>
            /// <returns></returns>
            internal static bool CreateObjectFromConfigEx(this ConfigNode node, object obj, ConfigNodeTypeHandler typeFormatter = null)
            {
                bool flag = true;

                typeFormatter = typeFormatter ?? new ConfigNodeTypeHandler();


                var fields     = GetObjectFields(obj);
                var properties = GetObjectProperties(obj);

                Log.Debug("CreateObjectFromConfig: Found {0} fields and {1} properties", fields.Length, properties.Length);

                #region fields

                foreach (var field in fields)
                {
                    try
                    {
                        System.Object[] attributes = field.GetCustomAttributes(true);

                        if (typeof(ConfigNode).IsAssignableFrom(field.FieldType))
                        {
                            Log.Debug("Field {0} is a ConfigNode", field.Name);

                            if (node.HasNode(field.Name))
                            {
                                ConfigNode target  = Convert.ChangeType(field.GetValue(obj) ?? new ConfigNode(), typeof(ConfigNode)) as ConfigNode;
                                ConfigNode subNode = node.GetNode(field.Name);

                                // handle subsection
                                Subsection ss = attributes.SingleOrDefault(attr => attr is Subsection) as Subsection;

                                if (ss != null)
                                {
                                    Log.Debug("ConfigNode field {0} under subsection {1}", field.Name, ss.Section);

                                    if (subNode.HasNode(ss.Section))
                                    {
                                        subNode = subNode.GetNode(ss.Section);
                                    }
                                    else
                                    {
                                        Log.Warning("Field {0} tagged with Subsection {1} but no such section exists!", field.Name, ss.Section);
                                    }
                                }
                                else
                                {
                                    Log.Debug("ConfigNode field {0} not under any subsection", field.Name);
                                }

                                // remember that subnode is the container for the node we wanted
                                if (subNode.CountNodes == 1)
                                {
                                    ConfigNode data = subNode.nodes[0]; // here's what we're interested in

                                    field.SetValue(obj, data);
                                    Log.Verbose("Successfully deserialized ConfigNode {0}", field.Name);
                                }
                                else
                                {
                                    Log.Warning("Storage for ConfigNode {0} looks like it's missing or wrong", field.Name);
                                }
                            }
                            else
                            {
                                Log.Warning("No serialized ConfigNode found for ConfigNode {0}", field.Name);
                            }
                        }
                        else
                        {
                            string strValue = ReadValue(node, field.Name, field.GetCustomAttributes(true));

                            if (!string.IsNullOrEmpty(strValue))
                            {
                                Log.Verbose("Parsing field {0}.{1} from {2}", obj.GetType().Name, field.Name, strValue ?? "");

                                MethodInfo mi = typeFormatter.GetType().GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.NonPublic);
                                if (mi == null)
                                {
                                    Log.Error("CreateObjectFromConfigEx: Failed to locate Deserialize method");
                                }

                                MethodInfo deserialize = mi.MakeGenericMethod(field.FieldType);
                                if (deserialize == null)
                                {
                                    Log.Error("CreateObjectFromConfigEx: Failed to create generic method for field {0}", field.FieldType.Name);
                                }

                                if (!(bool)deserialize.Invoke(typeFormatter, new object[] { field.GetValue(obj), strValue }))
                                {
                                    flag = false;
                                    Log.Warning("Failed to deserialize field {0}.{1} from {2}", obj.GetType().Name, field.FieldType.Name, strValue ?? "");
                                }
                                else
                                {
                                    Log.Verbose("Deserialized: {0}", field.GetValue(obj));
                                }
                            }
                            else
                            {
                                Log.Warning("CreateObjectFromConfigEx: Empty/null string found for field named {0}, type {1}", field.Name, field.FieldType.Name);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error("Exception while deserializing field '{0}': {1}", field.Name, e);
                        flag = false;
                    }
                }

                #endregion

                #region properties

                foreach (var property in properties)
                {
                    try
                    {
                        string strValue = ReadValue(node, property.Name, property.GetCustomAttributes(true));

                        if (!string.IsNullOrEmpty(strValue))
                        {
                            Log.Verbose("Parsing property {0}.{1} from {2}", obj.GetType().Name, property.Name, strValue ?? "");

                            MethodInfo mi = typeFormatter.GetType().GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (mi == null)
                            {
                                Log.Error("CreateObjectFromConfigEx: Failed to locate Deserialize method");
                            }

                            MethodInfo deserialize = mi.MakeGenericMethod(property.PropertyType);
                            if (deserialize == null)
                            {
                                Log.Error("CreateObjectFromConfigEx: Failed to create generic method for property {0}", property.PropertyType.Name);
                            }

                            // get existing value
                            var existing = Convert.ChangeType(property.GetGetMethod(true).Invoke(obj, null), property.PropertyType);

                            //object[] parameters = new object[] { Activator.CreateInstance(property.PropertyType), strValue };
                            object[] parameters = new object[] { existing, strValue };

                            if (!(bool)deserialize.Invoke(typeFormatter, parameters))
                            {
                                flag = false;
                                Log.Warning("Failed to deserialize property {0}.{1} from {2}", obj.GetType().Name, property.PropertyType.Name, strValue ?? "");
                            }
                            else
                            {
                                // use the actual setter
                                property.SetValue(obj, parameters[0], BindingFlags.SetProperty | BindingFlags.Instance, null, null, null);
                            }
                        }
                        else
                        {
                            Log.Warning("CreateObjectFromConfigEx: Empty/null string found for property named {0}, type {1}", property.Name, property.PropertyType.Name);
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error("Exception while deserializing property '{0}': {1}", property.Name, e);
                        flag = false;
                    }
                }

                #endregion

                if (obj is IReeperSerializable)
                {
                    ((IReeperSerializable)obj).OnDeserialize(node);
                }

                return(flag && fields.Count() > 0 || (obj is IReeperSerializable));
            }
示例#2
0
            /// <summary>
            /// Creates a ConfigNode out of the specified object, capturing non-static fields and properties that
            /// have both a setter and getter
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="typeFormatter"></param>
            /// <returns></returns>
            internal static ConfigNode CreateConfigFromObjectEx(this object obj, ConfigNodeTypeHandler typeFormatter = null)
            {
                try
                {
                    ConfigNode n = new ConfigNode(obj.GetType().Name);
                    typeFormatter = typeFormatter ?? new ConfigNodeTypeHandler();


                    // check if typeformatter has a serialize method for this type


                    #region serialize fields

                    var fields = GetObjectFields(obj);

                    foreach (var field in fields)
                    {
                        System.Object[] attributes = field.GetCustomAttributes(false);

                        var result = field.GetValue(obj);

                        if (result != null)
                        {
                            // check for ConfigNodes; they're a special case
                            if (typeof(ConfigNode).IsAssignableFrom(field.FieldType))
                            {
                                Log.Debug("{0} is a ConfigNode", field.Name);

                                // store ConfigNode in a subnode (so ConfigNode "test" would be stored in
                                // a subnode called "test" which then contains a copy of the ConfigNode). Do
                                // it this way so that any possible name the ConfigNode has doesn't collide
                                //
                                // why not rename it to field.name? we're not sure whether the node name matters
                                // to whichever objects are storing data there and we don't want to impose any
                                // arbitrary restrictions if we can avoid doing so
                                var subnode = new ConfigNode(field.Name);


                                //if (ss != null)
                                //    subnode = subnode.AddNode(ss.Section);

                                var copy = ((ConfigNode)Convert.ChangeType(result, typeof(ConfigNode))).CreateCopy();
                                if (string.IsNullOrEmpty(copy.name))
                                {
                                    copy.name = "ConfigNode";
                                }

                                Log.Debug("ConfigNode copy = {0}", copy.ToString());
                                Log.Debug("Original = {0}", ((ConfigNode)Convert.ChangeType(result, typeof(ConfigNode))).ToString());

                                subnode.ClearData();

                                // handle subsection attribute on ConfigNode fields
                                Subsection ss = attributes.SingleOrDefault(attr => attr is Subsection) as Subsection;

                                if (ss == null)
                                {
                                    subnode.AddNode(copy);
                                }
                                else
                                {
                                    subnode.AddNode(ss.Section).AddNode(copy);

                                    Log.Debug("Subnode with subsection = {0}", subnode.ToString());
                                }

                                n.AddNode(subnode);
                            }
                            else
                            {
                                MethodInfo mi = typeFormatter.GetType().GetMethod("Serialize", BindingFlags.Instance | BindingFlags.NonPublic);
                                if (mi == null)
                                {
                                    Log.Error("CreateConfigFromObjectEx: Serialize method not found");
                                }

                                MethodInfo serialize = mi.MakeGenericMethod(field.FieldType);
                                if (serialize == null)
                                {
                                    Log.Error("CreateConfigFromObjectEx: Failed to create generic method for {0}", field.FieldType.Name);
                                }

                                string serialized = serialize.Invoke(typeFormatter, new object[] { result }) as string;

                                if (string.IsNullOrEmpty(serialized))
                                {
                                    Log.Warning("ConfigUtil.CreateConfigFromObjectEx: null or empty return value for serialized type {0}", field.FieldType.Name);
                                }


                                WriteValue(n, field.Name, serialized, attributes);
                            }
                        }
                        else
                        {
                            Log.Warning("Could not get value for " + field.Name);
                        }
                    }

                    #endregion

                    #region serialize get/settable properties

                    var properties = GetObjectProperties(obj);


                    foreach (PropertyInfo property in properties)
                    {
                        Log.Verbose("Serializing property {0}, type {1}", property.Name, property.PropertyType.Name);
                        var propertyValue = property.GetGetMethod(true).Invoke(obj, null);

                        System.Object[] attributes = property.GetCustomAttributes(true);

                        MethodInfo mi = typeFormatter.GetType().GetMethod("Serialize", BindingFlags.Instance | BindingFlags.NonPublic);
                        if (mi == null)
                        {
                            Log.Error("CreateConfigFromObjectEx: Serialize method not found");
                            continue;
                        }

                        MethodInfo serialize = mi.MakeGenericMethod(property.PropertyType);
                        if (serialize == null)
                        {
                            Log.Error("CreateConfigFromObjectEx: Failed to create generic method for {0}", property.PropertyType.Name);
                        }

                        string serialized = serialize.Invoke(typeFormatter, new object[] { propertyValue }) as string;

                        if (string.IsNullOrEmpty(serialized))
                        {
                            Log.Warning("ConfigUtil.CreateConfigFromObjectEx: null or empty return value for serialized type {0}", property.PropertyType.Name);
                        }


                        WriteValue(n, property.Name, serialized, attributes);
                    }

                    #endregion

                    if (obj is IReeperSerializable)
                    {
                        ((IReeperSerializable)obj).OnSerialize(n);
                    }

                    return(n);
                }
                catch (Exception e)
                {
                    Log.Error("ConfigUtil.CreateConfigFromObjectEx: Exception {0}", e);
                    return(null);
                }
            }