예제 #1
0
                public static void ReadFromReader(this ICommand command, BigEndianReader read)
                {
                    var properties = command.GetType().GetProperties()
                                     .Where(f => f.GetCustomAttribute <CommandFieldAttribute>() != null)
                                     .Select(f => new { Property = f, Metadata = f.GetCustomAttribute <CommandFieldAttribute>() });

                    while (true)
                    {
                        byte fieldID = read.ReadByte();
                        if (fieldID == 255 || read.PeekChar() < 0)
                        {
                            break;
                        }

                        ushort fieldLength = read.ReadUInt16();

                        var fieldInfo         = properties.First(f => f.Metadata.FieldID == fieldID);
                        var serializationType = fieldInfo.Property.PropertyType;
                        if (fieldInfo.Metadata.SerializeAs != null)
                        {
                            serializationType = fieldInfo.Metadata.SerializeAs;
                        }

                        if (Nullable.GetUnderlyingType(serializationType) != null)
                        {
                            serializationType = Nullable.GetUnderlyingType(serializationType);
                        }

                        if (fieldInfo.Metadata.Repeated)
                        {
                            if (!serializationType.GetInterfaces().Any(i => i == typeof(IList)))
                            {
                                throw new Exception("Repeated field is not of a list type");
                            }

                            var listType = serializationType.GetInterfaces().First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList <>));
                            var internalSerializationType = listType.GetGenericArguments()[0];

                            var cur = fieldInfo.Property.GetValue(command) as IList;
                            if (!serializationType.IsArray)
                            {
                                if (cur == null)
                                {
                                    cur = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(internalSerializationType));
                                }
                                cur.Add(read.ReadOfType(fieldLength, internalSerializationType));
                            }
                            else
                            {
                                if (cur == null)
                                {
                                    cur = Array.CreateInstance(internalSerializationType, 1);
                                }
                                else
                                {
                                    var arr = Array.CreateInstance(internalSerializationType, cur.Count + 1);
                                    Array.Copy((Array)cur, arr, cur.Count);
                                    cur = arr;
                                }

                                cur[cur.Count - 1] = read.ReadOfType(fieldLength, internalSerializationType);
                            }

                            fieldInfo.Property.SetValue(command, cur);
                        }
                        else
                        {
                            var value = read.ReadOfType(fieldLength, serializationType);
                            if (serializationType != fieldInfo.Property.PropertyType)
                            {
                                if (!fieldInfo.Property.PropertyType.IsEnum)
                                {
                                    value = Convert.ChangeType(value, fieldInfo.Property.PropertyType);
                                }
                            }

                            fieldInfo.Property.SetValue(command, value);
                        }
                    }
                }