コード例 #1
0
        /// <summary>
        /// Cache all supported properties for a specific type.
        /// </summary>
        /// <param name="type">The type to cache all supported properties for.</param>
        private static void CachePropertiesFromType(Type type)
        {
            //We have yet to create a local cache of all supported properties of
            //the type of the object being serialized. Prepare a new list and
            //prepare to fill it with all properties we can support.
            List <PropertyInfo> listProp = new List <PropertyInfo>();

            foreach (var propInfo in type.GetProperties())
            {
                //Check to see if the property can be serialized or not
                if (PropertySerializer.CanSerializeProperty(propInfo))
                {
                    //The property can be serialized, add it to the list.
                    listProp.Add(propInfo);
                }
            }
            //Add the list of supported properties into our local cache.
            _cachedProperties.Add(type, listProp.ToArray());
        }
コード例 #2
0
        /// <summary>
        /// Seralise an object.
        /// </summary>
        /// <param name="data">The object itself that is being serialized.</param>
        /// <returns>A string representing a serialized value of the object.</returns>
        public string Serialize(object data)
        {
            /*
             * This serializer works a little different that normal serializer. All objects are formatted as
             * following and recursively:
             *	Basic value types:
             *		FullNameOfTheObject:TheValue
             *
             *			If we are trying to parse an integer of value 4, the output would be:
             *				Int32:4
             *			If we were trying to parse a double value of 4.3645 the output would be:
             *				Double:4.3645
             *			Before the semicolon is the name of the type without the "System." in front
             *			and after the semicolon comes the value parsed using the ToString() method.
             *
             *	Arrays:
             *		FullNameOfTheObjectPlusNamespace:[...]
             *
             *			The dots are comma seperated values that contain the serialized value of the objects
             *			inside the array. If we have an array of integers containing the values of 4, 6 and 3
             *			the output would be like so:
             *				System.Int32[]:[Int32:4,Int32:6,Int32:3]
             *			The value of each contains the name of the type and it is so because then we
             *			can have an aray of objects which contain an integer of 5, a double value of 6.43 and
             *			a custom object. With this the result would be like so:
             *				System.Object[]:[Int32:5,Double:6.43,NameOfNamespace.OurObject:{...}]
             *			For more information on how objects are parsed look below.
             *
             *	Custom objects and such:
             *		FullNameOfTheObjectPlusNamespace:{...}
             *
             *			Inside the brackets comes all properties that are supported in the following serialized format:
             *				NameOfProperty=xxx;
             *			The xxx represent the value run through the serializer recursively, so if we have a property
             *			called 'NumberOfUnits' and has an integer value of 2, the output would be following:
             *				NumberOfUnits=Int32:2;
             *
             */

            //Basic check to see if the data really is data.
            if (data != null)
            {
                //Create a local copy of the data.
                _data = data;

                //Check to make sure we are not serialising an already serialized objects
                if (_serializedObjects.Contains(data))
                {
                    //Object contained a reference to itself but was not an INetworkData object.
                    //In order to fully support circular reference, the object must be INetworkData.
                    //This can also happen if 2 different objects contain a reference to the same object.
                    throw new SerializerException("A circular reference was detected on an object that was not of type INetworkData. Make sure all circular reference objects are of type INetworkData. This also applies if 2 different objects contain a reference to the same object then that object must also be an INetworkData object.", data);
                }

                //Create a local copy of the type of the object.
                _dataType = _data.GetType();

                //The serialized value of the object
                string output = "";

                //If the object being serialized is a basic System type we don't need to write
                //the full name of it. Instead for example 'System.Int32' we get 'Int32', short
                //and simple.
                if (_dataType.FullName == "System." + _dataType.Name)
                {
                    output += _dataType.Name + ":";
                }
                else
                if (_dataType.UnderlyingSystemType != null && _dataType.UnderlyingSystemType.Name.Contains("ReadOnly"))
                {
                    output += _dataType.DeclaringType.FullName + ":";
                }
                else
                {
                    output += _dataType.FullName + ":";
                }

                //If the object is a basic value type, all we have to do is run ToString method
                //and be done with it.
                if (_data is string)
                {
                    return(String.Format("{0}\"{1}\"", output, (_data as string).Replace("\"", "\\\"")));
                }
                else if (_data is ValueType)
                {
                    return(output + (_data).ToString());
                }

                //Check to see if the object is an array or a collection of some sort.
                if (_data is Array)
                {
                    //We are parsing an array, prepare a new serializer and parse all of it's values.
                    output += "[";
                    Serializer ser = new Serializer();
                    for (int i = 0; i < (_data as IList).Count; i++)
                    {
                        //The contents of an array is a comma seperated value of the contents.
                        if (i > 0)
                        {
                            output += "," + ser.Serialize((_data as IList)[i]);
                        }
                        else
                        {
                            output += ser.Serialize((_data as IList)[i]);
                        }
                    }
                    return(output + "]");
                }
                else
                {
                    //We are parsing a normal object. Parse all supported properties inside the object.
                    output += "{";

                    //We create a cache of all valid properties of a given type due to the nature that
                    //checking whether a property is supported or not is a slow process.
                    if (!_cachedProperties.ContainsKey(_dataType))
                    {
                        CachePropertiesFromType(_dataType);
                    }

                    //Save our object into the collection. If any property contains a reference to itself
                    //then we will know about it by checking if it exists in the collection.
                    _serializedObjects.Add(data);

                    //Run through each property of the object and parse it's value
                    foreach (var propInfo in _cachedProperties[_dataType])
                    {
                        //PropertSerializer takes care of this for us.
                        PropertySerializer serProp = new PropertySerializer(_data, propInfo)
                        {
                            SerializedObjects = _serializedObjects
                        };
                        output += serProp.Serialize() + ";";
                    }
                    return(output + "}");
                }
            }
            else
            {
                return("null");
            }
        }