public static void Serialize <T>(BinaryWriter writer, Type type, bool nullable, T value) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>)) { Type underlyingType = type.GetGenericArguments()[0]; Serialize(writer, underlyingType, true, value); return; } if (nullable) { if (value == null) { writer.Write((byte)0); return; } writer.Write((byte)1); } else if (value == null) { throw new SerializationException("Trying to serialize a non Nullable null value"); } Action <BinaryWriter, object, bool> serializerFunc; if (WriteFunctions.TryGetValue(type, out serializerFunc)) { serializerFunc(writer, value, nullable); return; } if (type.IsEnum) { Type underlyingType = Enum.GetUnderlyingType(type); if (WriteFunctions.TryGetValue(underlyingType, out serializerFunc)) { serializerFunc(writer, Convert.ChangeType(value, underlyingType), nullable); } else { throw new SerializationException("Enum " + type.Name + " underlying type is not serializable."); } return; } SerializableTypeInfo serTypeInfo = SerializableTypeCache[type]; if (serTypeInfo != null) { if (serTypeInfo.SerializeMethod.IsStatic) { serTypeInfo.SerializeMethod.Invoke(null, new object[] { value, writer }); } else { serTypeInfo.SerializeMethod.Invoke(value, new object[] { writer }); } return; } Type elementType = GetListElementType(type); if (elementType != null) { Action <BinaryWriter, object, bool> writeFunc = (wrtr, vlue, nlble) => { wrtr.Write(checked ((ushort)((ICollection)vlue).Count)); foreach (var el in (IEnumerable)vlue) { Serialize(wrtr, elementType, nlble, el); } }; WriteFunctions[type] = writeFunc; writeFunc(writer, value, nullable); return; } foreach (var info in RpcInterface.GetOrederedFields(type)) { if (!info.IsStatic) { Serialize(writer, info.FieldType, NullableParamCache.Contains(info), info.GetValue(value)); } } foreach (var info in RpcInterface.GetOrderedProperties(type)) { if (info.CanRead && info.CanWrite) { Serialize(writer, info.PropertyType, NullableParamCache.Contains(info), info.GetValue(value, null)); } } }
public static object Deserialize(BinaryReader reader, Type type, bool nullable) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>)) { Type underlyingType = type.GetGenericArguments()[0]; return(Deserialize(reader, underlyingType, true)); } if (nullable && reader.ReadByte() == 0) { return(null); } Func <BinaryReader, bool, object> deserializerFunc; if (ReadFunctions.TryGetValue(type, out deserializerFunc)) { return(deserializerFunc(reader, nullable)); } if (type.IsEnum) { Type underlyingType = Enum.GetUnderlyingType(type); if (ReadFunctions.TryGetValue(underlyingType, out deserializerFunc)) { object value = deserializerFunc(reader, nullable); return(Enum.ToObject(type, value)); } throw new SerializationException("Enum " + type.Name + " underlying type is not serializable."); } SerializableTypeInfo serTypeInfo = SerializableTypeCache[type]; if (serTypeInfo != null) { if (serTypeInfo.DeserializeMethod != null) { return(serTypeInfo.DeserializeMethod.Invoke(null, new object[] { reader })); } if (serTypeInfo.Constructor != null) { return(Activator.CreateInstance(type, reader)); } } Type elementType = GetListElementType(type); if (elementType != null) { Func <BinaryReader, bool, object> readFunc; if (type.IsArray) { readFunc = (rdr, nlble) => { int length = rdr.ReadUInt16(); var array = (Array)Activator.CreateInstance(type, length); for (int i = 0; i < length; ++i) { array.SetValue(Deserialize(rdr, elementType, nlble), i); } return(array); }; } else { Type listType = typeof(List <>).MakeGenericType(elementType); readFunc = (rdr, nlble) => { int length = rdr.ReadUInt16(); var list = (IList)Activator.CreateInstance(listType); for (int i = 0; i < length; ++i) { list.Add(Deserialize(rdr, elementType, nlble)); } return(list); }; } ReadFunctions[type] = readFunc; return(readFunc(reader, nullable)); } var obj = Activator.CreateInstance(type); foreach (var info in RpcInterface.GetOrederedFields(type)) { if (!info.IsStatic) { var fieldValue = Deserialize(reader, info.FieldType, NullableParamCache.Contains(info)); info.SetValue(obj, fieldValue); } } foreach (var info in RpcInterface.GetOrderedProperties(type)) { if (info.CanRead && info.CanWrite) { var propValue = Deserialize(reader, info.PropertyType, NullableParamCache.Contains(info)); info.SetValue(obj, propValue, null); } } return(obj); }