コード例 #1
0
        private void ToBytesEnumerable(IEnumerable values, int length, SerializerTypeDetails typeDetail, ref ByteWriter writer)
        {
            writer.Write(length); //object count

            if (typeDetail.TypeDetail.CoreType.HasValue)
            {
                ToBytesCoreTypeEnumerable(values, length, typeDetail.TypeDetail.CoreType.Value, ref writer);
                return;
            }

            if (typeDetail.TypeDetail.EnumUnderlyingType.HasValue)
            {
                ToBytesEnumTypeEnumerable(values, length, typeDetail.TypeDetail.EnumUnderlyingType.Value, ref writer);
                return;
            }

            if (typeDetail.TypeDetail.SpecialType.HasValue || typeDetail.TypeDetail.IsNullable && typeDetail.InnerTypeDetail.TypeDetail.SpecialType.HasValue)
            {
                ToBytesSpecialTypeEnumerable(values, length, typeDetail, ref writer);
                return;
            }

            foreach (var value in values)
            {
                if (value == null)
                {
                    writer.Write(false); //no object
                    continue;
                }
                writer.Write(true); //has object

                ToBytes(value, typeDetail, false, ref writer);
            }
        }
コード例 #2
0
        private void ToBytesSpecialTypeEnumerable(IEnumerable values, int length, SerializerTypeDetails typeDetail, ref ByteWriter writer)
        {
            var specialType = typeDetail.TypeDetail.IsNullable ? typeDetail.InnerTypeDetail.TypeDetail.SpecialType.Value : typeDetail.TypeDetail.SpecialType.Value;

            switch (specialType)
            {
            case SpecialType.Type:
            {
                foreach (var valueType in (IEnumerable <Type>)values)
                {
                    writer.Write(valueType?.FullName, true);
                }
                return;
            }

            case SpecialType.Dictionary:
            {
                foreach (var value in values)
                {
                    if (value != null)
                    {
                        writer.WriteNotNull();
                        var method     = TypeAnalyzer.GetGenericMethodDetail(enumerableToArrayMethod, typeDetail.TypeDetail.IEnumerableGenericInnerType);
                        var innerValue = (ICollection)method.Caller(null, new object[] { value });
                        var count      = innerValue.Count;
                        ToBytesEnumerable(innerValue, count, typeDetail.InnerTypeDetail, ref writer);
                    }
                    else
                    {
                        writer.WriteNull();
                    }
                }
                return;
            }

            default:
                throw new NotImplementedException();
            }
        }
コード例 #3
0
        private void ToBytesSpecialType(object value, SerializerTypeDetails typeDetail, bool nullFlags, ref ByteWriter writer)
        {
            var specialType = typeDetail.TypeDetail.IsNullable ? typeDetail.InnerTypeDetail.TypeDetail.SpecialType.Value : typeDetail.TypeDetail.SpecialType.Value;

            switch (specialType)
            {
            case SpecialType.Type:
            {
                var valueType = value == null ? null : (Type)value;
                writer.Write(valueType?.FullName, nullFlags);
            }
                return;

            case SpecialType.Dictionary:
            {
                if (value != null)
                {
                    if (nullFlags)
                    {
                        writer.WriteNotNull();
                    }
                    var method     = TypeAnalyzer.GetGenericMethodDetail(enumerableToArrayMethod, typeDetail.TypeDetail.IEnumerableGenericInnerType);
                    var innerValue = (ICollection)method.Caller(null, new object[] { value });
                    var count      = innerValue.Count;
                    ToBytesEnumerable(innerValue, count, typeDetail.InnerTypeDetail, ref writer);
                }
                else if (nullFlags)
                {
                    writer.WriteNull();
                }
            }
                return;

            default:
                throw new NotImplementedException();
            }
        }
コード例 #4
0
        private void ToBytes(object value, SerializerTypeDetails typeDetail, bool nullFlags, ref ByteWriter writer)
        {
            if (includePropertyTypes)
            {
                var    typeFromValue = value.GetType();
                string typeName      = typeFromValue.FullName;
                writer.Write(typeName, false);
                typeDetail = GetTypeInformation(typeFromValue, this.indexSize, this.ignoreIndexAttribute);
            }
            else if (typeDetail.Type.IsInterface && !typeDetail.TypeDetail.IsIEnumerableGeneric && value != null)
            {
                var objectType = value.GetType();
                typeDetail = GetTypeInformation(objectType, this.indexSize, this.ignoreIndexAttribute);
            }
            else if (typeDetail == null)
            {
                throw new InvalidOperationException("Must include type information to deserialize without specifying a type.");
            }

            if (typeDetail.TypeDetail.CoreType.HasValue)
            {
                ToBytesCoreType(value, typeDetail.TypeDetail.CoreType.Value, nullFlags, ref writer);
                return;
            }

            if (typeDetail.TypeDetail.EnumUnderlyingType.HasValue)
            {
                ToBytesEnumType(value, typeDetail.TypeDetail.EnumUnderlyingType.Value, nullFlags, ref writer);
                return;
            }

            if (typeDetail.TypeDetail.SpecialType.HasValue || typeDetail.TypeDetail.IsNullable && typeDetail.InnerTypeDetail.TypeDetail.SpecialType.HasValue)
            {
                ToBytesSpecialType(value, typeDetail, nullFlags, ref writer);
                return;
            }

            if (typeDetail.TypeDetail.IsIEnumerableGeneric)
            {
                if (typeDetail.TypeDetail.IsICollection)
                {
                    var collection = (ICollection)value;
                    var count      = collection.Count;
                    ToBytesEnumerable(collection, count, typeDetail.InnerTypeDetail, ref writer);
                }
                else if (typeDetail.TypeDetail.IsICollectionGeneric)
                {
                    var count = (int)typeDetail.TypeDetail.GetMember("Count").Getter(value);
                    ToBytesEnumerable((IEnumerable)value, count, typeDetail.InnerTypeDetail, ref writer);
                }
                else
                {
                    var enumerable = (IEnumerable)value;
                    var count      = 0;
                    foreach (var item in enumerable)
                    {
                        count++;
                    }
                    ToBytesEnumerable(enumerable, count, typeDetail.InnerTypeDetail, ref writer);
                }
                return;
            }

            if (nullFlags)
            {
                if (value == null)
                {
                    writer.Write(false); //no object
                    return;
                }
                writer.Write(true); //has object
            }
            foreach (var indexProperty in typeDetail.IndexedProperties)
            {
                object propertyValue = indexProperty.Value.Getter(value);
                if (propertyValue != null)
                {
                    if (usePropertyNames)
                    {
                        writer.Write(indexProperty.Value.Name, false);
                    }
                    else
                    {
                        switch (this.indexSize)
                        {
                        case ByteSerializerIndexSize.Byte:
                            writer.Write((byte)indexProperty.Key);
                            break;

                        case ByteSerializerIndexSize.UInt16:
                            writer.Write(indexProperty.Key);
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    ToBytes(propertyValue, indexProperty.Value.SerailzierTypeDetails, false, ref writer);
                }
            }

            if (usePropertyNames)
            {
                writer.Write(0);
            }
            else
            {
                switch (this.indexSize)
                {
                case ByteSerializerIndexSize.Byte:
                    writer.Write(endObjectFlagByte);
                    break;

                case ByteSerializerIndexSize.UInt16:
                    writer.Write(endObjectFlagUInt16);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
コード例 #5
0
        private object FromBytes(ref ByteReader reader, SerializerTypeDetails typeDetail, bool nullFlags, bool drainBytes)
        {
            if (!drainBytes && typeDetail == null)
            {
                throw new NotSupportedException("Cannot deserialize without type information");
            }
            if (includePropertyTypes)
            {
                string typeName      = reader.ReadString(false);
                var    typeFromBytes = Discovery.GetTypeFromName(typeName);
                //overrides potentially boxed type with actual type if exists in assembly
                if (typeFromBytes != null)
                {
                    var newTypeDetail = GetTypeInformation(typeFromBytes, this.indexSize, this.ignoreIndexAttribute);

                    var typeDetailCheck = typeDetail.TypeDetail;
                    if (typeDetailCheck.IsNullable)
                    {
                        typeDetailCheck = typeDetailCheck.InnerTypeDetails[0];
                    }
                    var newTypeDetailCheck = newTypeDetail.TypeDetail;

                    if (newTypeDetailCheck.Type != typeDetailCheck.Type && !newTypeDetailCheck.Interfaces.Contains(typeDetailCheck.Type) && !newTypeDetail.TypeDetail.BaseTypes.Contains(typeDetailCheck.Type))
                    {
                        throw new NotSupportedException($"{newTypeDetail.Type.GetNiceName()} does not convert to {typeDetail.TypeDetail.Type.GetNiceName()}");
                    }

                    typeDetail = newTypeDetail;
                }
            }
            else if (typeDetail.Type.IsInterface && !typeDetail.TypeDetail.IsIEnumerableGeneric)
            {
                var emptyImplementationType = EmptyImplementations.GetEmptyImplementationType(typeDetail.Type);
                typeDetail = GetTypeInformation(emptyImplementationType, this.indexSize, this.ignoreIndexAttribute);
            }

            if (typeDetail.TypeDetail.CoreType.HasValue)
            {
                return(FromBytesCoreType(ref reader, typeDetail.TypeDetail.CoreType.Value, nullFlags));
            }

            if (typeDetail.TypeDetail.EnumUnderlyingType.HasValue)
            {
                var    numValue = FromBytesCoreType(ref reader, typeDetail.TypeDetail.EnumUnderlyingType.Value, nullFlags);
                object value;
                if (!typeDetail.TypeDetail.IsNullable)
                {
                    value = Enum.ToObject(typeDetail.Type, numValue);
                }
                else if (numValue != null)
                {
                    value = Enum.ToObject(typeDetail.TypeDetail.InnerTypes[0], numValue);
                }
                else
                {
                    value = null;
                }
                return(value);
            }

            if (typeDetail.TypeDetail.SpecialType.HasValue || typeDetail.TypeDetail.IsNullable && typeDetail.InnerTypeDetail.TypeDetail.SpecialType.HasValue)
            {
                return(FromBytesSpecialType(ref reader, typeDetail, nullFlags));
            }

            if (typeDetail.TypeDetail.IsIEnumerableGeneric)
            {
                var enumerable = FromBytesEnumerable(ref reader, typeDetail.InnerTypeDetail, !typeDetail.TypeDetail.Type.IsArray && typeDetail.TypeDetail.IsIList);
                return(enumerable);
            }

            if (nullFlags)
            {
                var hasObject = reader.ReadBoolean();

                if (!hasObject)
                {
                    return(null);
                }
            }

            object obj = typeDetail.TypeDetail.Creator();

            for (; ;)
            {
                SerializerMemberDetails indexProperty = null;

                if (usePropertyNames)
                {
                    string name = reader.ReadString(false);

                    if (name == String.Empty)
                    {
                        return(obj);
                    }

                    indexProperty = typeDetail.IndexedProperties.Values.FirstOrDefault(x => x.Name == name);

                    if (indexProperty == null)
                    {
                        if (!usePropertyNames && !includePropertyTypes)
                        {
                            throw new Exception($"Cannot deserialize with property {name} undefined and no types.");
                        }

                        //consume bytes but object does not have property
                        object value = FromBytes(ref reader, null, false, true);
                        indexProperty.Setter(obj, value);
                    }
                    else
                    {
                        object value = FromBytes(ref reader, indexProperty.SerailzierTypeDetails, false, false);
                        indexProperty.Setter(obj, value);
                    }
                }
                else
                {
                    var propertyIndex = this.indexSize switch
                    {
                        ByteSerializerIndexSize.Byte => (ushort)reader.ReadByte(),
                        ByteSerializerIndexSize.UInt16 => reader.ReadUInt16(),
                        _ => throw new NotImplementedException(),
                    };

                    if (propertyIndex == endObjectFlagUShort)
                    {
                        return(obj);
                    }

                    if (typeDetail.IndexedProperties.Keys.Contains(propertyIndex))
                    {
                        indexProperty = typeDetail.IndexedProperties[propertyIndex];
                    }

                    if (indexProperty == null)
                    {
                        if (!usePropertyNames && !includePropertyTypes)
                        {
                            throw new Exception($"Cannot deserialize with property {propertyIndex} undefined and no types.");
                        }

                        //consume bytes but object does not have property
                        object value = FromBytes(ref reader, null, false, true);
                        indexProperty.Setter(obj, value);
                    }
                    else
                    {
                        object value = FromBytes(ref reader, indexProperty.SerailzierTypeDetails, false, false);
                        indexProperty.Setter(obj, value);
                    }
                }
            }

            throw new Exception("Expected end of object marker");
        }
コード例 #6
0
        private object FromBytesEnumerable(ref ByteReader reader, SerializerTypeDetails typeDetail, bool asList)
        {
            int length = reader.ReadInt32();

            if (length == 0)
            {
                if (!asList)
                {
                    return(Array.CreateInstance(typeDetail.Type, length));
                }
                else
                {
                    return((IList)typeDetail.ListCreator(length));
                }
            }

            if (typeDetail.TypeDetail.CoreType.HasValue)
            {
                return(FromBytesCoreTypeEnumerable(ref reader, length, typeDetail.TypeDetail.CoreType.Value, asList));
            }

            if (typeDetail.TypeDetail.EnumUnderlyingType.HasValue)
            {
                if (!asList)
                {
                    var array = Array.CreateInstance(typeDetail.Type, length);
                    for (int i = 0; i < length; i++)
                    {
                        var    numValue = FromBytesCoreType(ref reader, typeDetail.TypeDetail.EnumUnderlyingType.Value, true);
                        object item;
                        if (!typeDetail.TypeDetail.IsNullable)
                        {
                            item = Enum.ToObject(typeDetail.Type, numValue);
                        }
                        else if (numValue != null)
                        {
                            item = Enum.ToObject(typeDetail.TypeDetail.InnerTypes[0], numValue);
                        }
                        else
                        {
                            item = null;
                        }
                        array.SetValue(item, i);
                    }
                    return(array);
                }
                else
                {
                    var list = (IList)typeDetail.ListCreator(length);
                    for (int i = 0; i < length; i++)
                    {
                        var    numValue = FromBytesCoreType(ref reader, typeDetail.TypeDetail.EnumUnderlyingType.Value, true);
                        object item;
                        if (!typeDetail.TypeDetail.IsNullable)
                        {
                            item = Enum.ToObject(typeDetail.Type, numValue);
                        }
                        else if (numValue != null)
                        {
                            item = Enum.ToObject(typeDetail.TypeDetail.InnerTypes[0], numValue);
                        }
                        else
                        {
                            item = null;
                        }
                        list.Add(item);
                    }
                    return(list);
                }
            }

            if (typeDetail.TypeDetail.SpecialType.HasValue || typeDetail.TypeDetail.IsNullable && typeDetail.InnerTypeDetail.TypeDetail.SpecialType.HasValue)
            {
                return(FromBytesSpecialTypeEnumerable(ref reader, length, typeDetail, asList));
            }

            object obj = null;

            if (!asList)
            {
                var array = Array.CreateInstance(typeDetail.Type, length);
                if (length == 0)
                {
                    return(array);
                }

                int count = 0;
                for (; ;)
                {
                    var hasObject = reader.ReadBoolean();
                    if (!hasObject)
                    {
                        count++;
                        if (count == length)
                        {
                            return(array);
                        }
                        continue;
                    }

                    obj = FromBytes(ref reader, typeDetail, false, false);
                    array.SetValue(obj, count);
                    count++;
                    if (count == length)
                    {
                        return(array);
                    }
                }

                throw new Exception("Expected end of object marker");
            }
            else
            {
                var list = (IList)typeDetail.ListCreator(length);
                if (length == 0)
                {
                    return(list);
                }

                int count = 0;
                for (; ;)
                {
                    var hasObject = reader.ReadBoolean();
                    if (!hasObject)
                    {
                        list.Add(null);
                        count++;
                        if (count == length)
                        {
                            return(list);
                        }
                        continue;
                    }

                    obj = FromBytes(ref reader, typeDetail, false, false);
                    list.Add(obj);
                    count++;
                    if (count == length)
                    {
                        return(list);
                    }
                }

                throw new Exception("Expected end of object marker");
            }
        }