Exemple #1
0
        /// <summary>
        /// Retrieve all StreamData properties contained within type.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static StreamDataInfo[] GetProperties(Type type)
        {
            StreamDataInfo[] retVal;
            // Try fetching from common cache
            if (cachedProperties.TryGetValue(type, out retVal))
            {
                return(retVal);
            }

            BindingFlags bind = BindingFlags.Instance | BindingFlags.Public;

            if (type.GetAttribute <StreamDataIncludeBaseAttribute>() == null)
            {
                bind |= BindingFlags.DeclaredOnly;
            }
            retVal = (from pi in type.GetProperties(bind)
                      let attr = (StreamDataAttribute)pi.GetCustomAttributes(typeof(StreamDataAttribute), true).FirstOrDefault()
                                 // Only consider SpellData properties
                                 where attr != null
                                 orderby attr.Order ascending
                                 select StreamDataInfo.Create(pi, attr)).ToArray();

            cachedProperties.TryAdd(type, retVal);
            return(retVal);
        }
        public static object[] GetPropertyValues(object obj)
        {
            var values = new List <object>();

            foreach (var p in StreamDataInfo.GetProperties(obj.GetType()))
            {
                values.Add(p.PropertyInfo.SafeGetValue(obj, null));
            }
            return(values.ToArray());
        }
        /// <summary>
        /// Retrieve human-readable display of PropertyName=Value
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string[] GetDebugInfo(object obj)
        {
            var values = new List <string>();

            foreach (var p in StreamDataInfo.GetProperties(obj.GetType()))
            {
                // Add each property tagged with SpellDataAttribute in the topmost class
                if (p.IsArray)
                {
                    dynamic values2 = p.PropertyInfo.SafeGetValue(obj, null);
                    values.Add(String.Format("{0}={1}", p.PropertyInfo.Name,
                                             "{ " + String.Join(", ", values2) + " }"));
                }
                else
                {
                    values.Add(String.Format("{0}={1}", p.PropertyInfo.Name, p.PropertyInfo.SafeGetValue(obj, null)));
                }
            }
            return(values.ToArray());
        }
        private bool WriteValue(Type dataType, SuperStream stream, object value)
        {
            if (dataType == typeof(Byte))
            {
                stream.WriteByte((byte)value);
                return(true);
            }

            if (dataType == typeof(Int64))
            {
                stream.WriteInt64((Int64)value);
                return(true);
            }
            if (dataType == typeof(UInt64))
            {
                stream.WriteUInt64((UInt64)value);
                return(true);
            }

            if (dataType == typeof(Int32))
            {
                stream.WriteInt32((Int32)value);
                return(true);
            }
            if (dataType == typeof(UInt32))
            {
                stream.WriteUInt32((UInt32)value);
                return(true);
            }

            if (dataType == typeof(Int16))
            {
                stream.WriteInt16((Int16)value);
                return(true);
            }
            if (dataType == typeof(UInt16))
            {
                stream.WriteUInt16((UInt16)value);
                return(true);
            }

            if (dataType == typeof(Single))
            {
                stream.WriteSingle((Single)value);
                return(true);
            }

            if (dataType == typeof(Double))
            {
                stream.WriteDouble((Double)value);
                return(true);
            }

            if (dataType == typeof(bool))
            {
                // If bool is true, write 1. Otherwise, write 0.
                int val = ((bool)value) ? 1 : 0;
                stream.WriteInt32(val);
            }

            if (dataType.IsEnum)
            {
                dynamic storeValue = Convert.ChangeType(value, Enum.GetUnderlyingType(dataType));
                return(this.WriteValue(storeValue.GetType(), stream, storeValue));
            }

            // Test if type has StreamDataAttribute on properties.
            // This allows nesting of StreamData-aware task.DataTypes
            var props = StreamDataInfo.GetProperties(dataType);

            if (props.Length == 0)
            {
                return(false);
            }

            StreamData.Serialize(value, stream);
            // Need to add error condition here.
            return(true);
        }
        private bool GetValue(Type dataType, SuperStream stream, out object value)
        {
            if (dataType == typeof(Byte))
            {
                value = (byte)stream.ReadByte();
                return(true);
            }

            if (dataType == typeof(Int64))
            {
                value = stream.ReadInt64();
                return(true);
            }
            if (dataType == typeof(UInt64))
            {
                value = stream.ReadUInt64();
                return(true);
            }

            if (dataType == typeof(Int32))
            {
                value = stream.ReadInt32();
                return(true);
            }
            if (dataType == typeof(UInt32))
            {
                value = stream.ReadUInt32();
                return(true);
            }

            if (dataType == typeof(Int16))
            {
                value = stream.ReadInt16();
                return(true);
            }
            if (dataType == typeof(UInt16))
            {
                value = stream.ReadUInt16();
                return(true);
            }

            if (dataType == typeof(Single))
            {
                value = stream.ReadSingle();
                return(true);
            }

            if (dataType == typeof(Double))
            {
                value = stream.ReadDouble();
                return(true);
            }

            if (dataType == typeof(bool))
            {
                var val = stream.ReadUInt32();
                if (val == 0)
                {
                    value = false;
                    return(true);
                }
                else if (val == 1)
                {
                    value = true;
                    return(true);
                }
                else
                {
                    throw new Exception("Parsing type bool: Expected value to be either 0 or 1, but it was " + val.ToString());
                }
            }

            if (dataType.IsEnum)
            {
                object readValue;
                // Read the enums underlying type
                if (!this.GetValue(Enum.GetUnderlyingType(dataType), stream, out readValue))
                {
                    value = null;
                    return(false);
                }
                // Parse enum using the read value.
                value = Enum.ToObject(dataType, readValue);
                return(true);
            }

            // Test if type has StreamDataAttribute on properties.
            // This allows nesting of StreamData-aware task.DataTypes
            var props = StreamDataInfo.GetProperties(dataType);

            if (props.Length == 0)
            {
                value = null;
                return(false);
            }

            value = StreamData.Create(dataType, stream);
            if (value == null)
            {
                return(false);
            }
            return(true);
        }
 public static StreamDataInfo[] GetProperties(Type type)
 {
     return(StreamDataInfo.GetProperties(type));
 }
        /// <summary>
        /// Write a given object to stream
        /// </summary>
        /// <param name="obj">Object to write</param>
        /// <param name="ms">Stream to write to</param>
        public static void Serialize(object obj, SuperStream ms)
        {
            if (typeof(IStreamDataFinalizer).IsAssignableFrom(obj.GetType()))
            {
                IStreamDataFinalizer fin = (IStreamDataFinalizer)obj;
                fin.OnSerialize();
            }
            var properties = StreamDataInfo.GetProperties(obj.GetType());

            // Parse spell arguments
            foreach (var pi in properties)
            {
                dynamic value             = pi.PropertyInfo.SafeGetValue(obj, null);
                StreamDataParserTask task = new StreamDataParserTask(ms, pi.ReadType, pi.DataType, pi.Attributes);

                if (pi.IsCollection)
                {
                    // Find actual length of collection.
                    ulong length;
                    if (pi.IsArray)
                    {
                        length = (ulong)value.Length;
                    }
                    else if (pi.IsList)
                    {
                        length = (ulong)value.Count;
                    }
                    else
                    {
                        throw new Exception("Property is collection, but not array nor list.");
                    }

                    // Write length, and return written length. (Entries= will override length of collection if set)
                    length = pi.WriteContentLength(ms, length);

                    dynamic enumerable = pi.PropertyInfo.SafeGetValue(obj, null);
                    ulong   count      = 0;
                    foreach (var entry in enumerable)
                    {
                        // Make sure we do not write more entries than we've declared
                        count++;
                        if (count > length)
                        {
                            throw new Exception("Collection contains more items than ");
                        }

                        // Write enry.
                        if (!WriteParserData(task, entry))
                        {
                            throw new Exception();
                        }
                    }
                    continue;
                }
                else
                {
                    if (!WriteParserData(task, value))
                    {
                        throw new Exception();
                    }
                }
            }
        }
        /// <summary>
        /// Populates an existing object with data from stream.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static object Populate(object obj, SuperStream ms)
        {
            var     properties        = StreamDataInfo.GetProperties(obj.GetType());
            bool    gracefulStopAtEOF = obj.GetType().GetAttribute <StreamDataGracefulEofAttribute>() != null;
            dynamic value;

            // Parse spell arguments
            foreach (var pi in properties)
            {
                if (gracefulStopAtEOF && ms.EOF)
                {
                    break;
                }
                StreamDataParserTask task = new StreamDataParserTask(ms, pi.ReadType, pi.DataType, pi.Attributes);

                if (pi.IsCollection)
                {
                    var entries = pi.ReadContentLength(ms);

                    if (pi.IsArray)
                    {
                        var arr = new ArrayList((int)Math.Min(int.MaxValue, entries));
                        for (ulong i = 0; i < entries; i++)
                        {
                            if (!GetParserData(task, out value))
                            {
                                throw new Exception();
                            }
                            arr.Add(value);
                        }

                        var arr2 = arr.ToArray(pi.ReadType);
                        pi.PropertyInfo.SafeSetValue(obj, arr2, null);
                        continue;
                    }
                    else if (pi.IsList)
                    {
                        dynamic list = Activator.CreateInstance(
                            typeof(List <>).MakeGenericType(pi.DataType),
                            (int)Math.Min(int.MaxValue, entries));

                        for (ulong i = 0; i < entries; i++)
                        {
                            if (!GetParserData(task, out value))
                            {
                                throw new Exception();
                            }
                            list.Add(value);
                        }
                        pi.PropertyInfo.SafeSetValue(obj, (object)list, null);
                    }
                }
                else
                {
                    if (!GetParserData(task, out value))
                    {
                        throw new Exception();
                    }
                    pi.PropertyInfo.SafeSetValue(obj, (object)value, null);
                    continue;
                }
            }
            if (typeof(IStreamDataFinalizer).IsAssignableFrom(obj.GetType()))
            {
                IStreamDataFinalizer fin = (IStreamDataFinalizer)obj;
                fin.OnDeserialize();
            }
            return(obj);
        }
Exemple #9
0
        public static StreamDataInfo Create(PropertyInfo pi, StreamDataAttribute attr)
        {
            var sdi = new StreamDataInfo
            {
                PropertyInfo = pi,
                Entries      = attr.Entries,
                IsArray      = false,
                IsList       = false,
                ReadType     = attr.ReadType,
                Attributes   = (from a in pi.GetCustomAttributes(true)
                                where a.GetType() != typeof(StreamDataAttribute)
                                where a is Attribute
                                select a as Attribute).ToArray()
            };

            sdi.IsArray = pi.PropertyType.IsArray;
            #region Check if it's a IList.
            if (pi.PropertyType.IsGenericType &&
                pi.PropertyType.GetGenericTypeDefinition() == typeof(List <>))
            {
                sdi.IsList = true;
            }


            #endregion

            #region Validate input and assign proper DataType
            if (sdi.ReadType != null && sdi.ReadType.IsArray)
            {
                throw new ArgumentException(String.Format("{0}->{1}: [StreamDataAttribute] specified ReadType=typeof({2}), but {2} is an array. Specify its member type {3} instead.",
                                                          pi.DeclaringType.FullName, pi.Name, sdi.ReadType.Name, sdi.ReadType.MemberType));
            }

            if (sdi.IsArray)
            {
                sdi.DataType = pi.PropertyType.GetElementType();
            }
            else if (sdi.IsList)
            {
                sdi.DataType = pi.PropertyType.GetGenericArguments().First();
            }
            else
            {
                sdi.DataType = pi.PropertyType;
            }

            if (sdi.ReadType == null)
            {
                sdi.ReadType = sdi.DataType;
            }
            #endregion
            #region Verify that collections have correct parameters
            if (sdi.IsCollection)
            {
                if (sdi.Entries != 0 && sdi.Attributes.FirstOrDefault(a => a is StreamDataCollectionLengthAttribute) != null)
                {
                    throw new ArgumentException(String.Format("{0}->{1}: Cannot specify both [StreamDataCollectionLengthAttribute] and [StreamDataAttribute].Entries>0.",
                                                              pi.DeclaringType.FullName, pi.Name, sdi.Entries));
                }
                if (sdi.Entries == 0 && sdi.Attributes.FirstOrDefault(a => a is StreamDataCollectionLengthAttribute) == null)
                {
                    throw new ArgumentException(String.Format("{0}->{1}: Collection must have either [StreamDataCollectionLengthAttribute] or [StreamDataAttribute] specifying Entries>0.",
                                                              pi.DeclaringType.FullName, pi.Name, sdi.Entries));
                }
            }
            #endregion

            return(sdi);
        }