static Tuple <PropertyInfo, StarSerializeAttribute> GetMember(PropertyInfo pInfo) { StarSerializeAttribute soa = pInfo.GetCustomAttribute <StarSerializeAttribute>(); if (soa == null) { return(null); } return(Tuple.Create(pInfo, soa)); }
static BlockExpression ReadMaybeType(Expression member, Expression stream, StarSerializeAttribute attrib) { var maybeType = member.Type.GetGenericArguments().First(); var hasAny = Expression.Variable(typeof(byte), "hasAny"); var valueProp = member.Type.GetProperty("Value"); var newExpr = Expression.Block(new[] { hasAny }, Expression.Assign(member, Expression.New(member.Type)), Expression.Assign(hasAny, Expression.Invoke(Expression.Constant(_serializables[typeof(byte)].Deserializer), stream)), Expression.IfThen(Expression.Equal(hasAny, Expression.Constant((byte)1)), ReadOne(stream, Expression.Property(member, valueProp), maybeType, null) ), member ); return(newExpr); }
static BlockExpression GetListReader(Expression stream, MemberExpression member, Expression reader, Type genericType, StarSerializeAttribute serializeAttrib) { var length = Expression.Variable(typeof(int), "length"); var listType = typeof(List <>).MakeGenericType(genericType); var list = Expression.Variable(listType, "list"); var exit = Expression.Label(); var block = Expression.Block(new[] { length, list }, Expression.Assign(list, Expression.New(listType)), ReadLengthIfNotGreedy(stream, member, length, serializeAttrib.Length), Expression.Loop( Expression.IfThenElse(ShouldReadMore(stream, member, GetListCount(list, genericType), length), Expression.Call(list, "Add", null, reader), Expression.Break(exit)), exit), list); return(block); }
static BlockExpression GetListWriter(Expression stream, MemberExpression member, Type genericType, Expression func, StarSerializeAttribute serializeAttrib) { var counter = Expression.Variable(typeof(int), "counter"); var exit = Expression.Label(); var listLength = GetListCount(member, genericType); var currentItem = Expression.Property(member, "Item", counter); var block = Expression.Block(new[] { counter }, WriteLengthIfNotGreedy(stream, member, listLength, serializeAttrib != null ? serializeAttrib.Length : 0), Expression.Loop( Expression.IfThenElse(Expression.LessThan(counter, listLength), Expression.Block( Expression.Invoke(func, stream, currentItem), Expression.Assign(counter, Expression.Increment(counter))), Expression.Break(exit)), exit)); return(block); }
static Expression ReadOne(Expression stream, MemberExpression dest, Type destType, StarSerializeAttribute serializeAttrib, bool toObj = false) { //If we're dealing with a collection, take the generic parameter type. var type = GetCollectionTypeOrSelf(destType); //If the type is complex, deserialize recursively, else read primitives. var func = IsComplex(type) ? PacketDeserializers.ContainsKey(type) ? PacketDeserializers[type] : BuildDeserializer(type) : GetSerializableType(type).Deserializer; var reader = Expression.Convert(Expression.Invoke(Expression.Constant(func), stream), type) as Expression; if (IsList(destType)) { return(Expression.Assign(dest, GetListReader(stream, dest, reader, type, serializeAttrib))); } else if (IsDictionary(destType)) { Type[] kvTypes = destType.GetGenericArguments(); Type valType = kvTypes[1]; var valFunc = IsComplex(valType) ? PacketDeserializers.ContainsKey(valType) ? PacketDeserializers[valType] : BuildDeserializer(valType) : GetSerializableType(valType).Deserializer; var valReader = Expression.Convert(Expression.Invoke(Expression.Constant(valFunc), stream), valType) as Expression; return(Expression.Assign(dest, GetDictionaryReader(stream, reader, valReader, type, valType))); } return(Expression.Assign(dest, toObj ? Expression.Convert(reader, typeof(object)) : reader)); }
static Expression WriteOne(Expression stream, MemberExpression source, Type sourceType, StarSerializeAttribute serializeAttrib) { try { var type = GetCollectionTypeOrSelf(sourceType); var isComplex = IsComplex(type); var func = isComplex ? PacketSerializers.ContainsKey(type) ? PacketSerializers[type] : BuildSerializer(type) : GetSerializableType(type).Serializer; if (IsList(sourceType)) { var w = GetListWriter(stream, source, type, Expression.Constant(func), serializeAttrib); return(w); } else if (IsDictionary(sourceType)) { Type[] kvTypes = sourceType.GetGenericArguments(); Type valType = kvTypes[1]; var valFunc = IsComplex(valType) ? PacketSerializers.ContainsKey(valType) ? PacketSerializers[valType] : BuildSerializer(valType) : GetSerializableType(valType).Serializer; return(GetDictionaryWriter(stream, source, type, valType, func, valFunc)); } var funcType = GetFuncType(func); //We need to downcast the member because of contravariance with enums or Complex type boxing. var writer = Expression.Invoke(Expression.Constant(func), stream, Expression.Convert(source, funcType)); return(writer); } catch (Exception ex) { ex.LogError(); throw; } }
//TODO: FIX ME //static BlockExpression ReadEitherType(MemberExpression member, Expression stream, StarSerializeAttribute attrib) //{ // Type[] eitherTypes = member.Type.GetGenericArguments(); // Type leftType = eitherTypes.First(); // Type maybeLeftType = typeof(Maybe<>).MakeGenericType(leftType); // var maybeLeft = Expression.Variable(maybeLeftType, "maybe"); // var maybeVal = maybeLeftType.GetProperty("Value"); // var eitherLeft = member.Type.GetProperty("Left"); // var eitherRight = member.Type.GetProperty("Right"); // var newExpr = Expression.Block(new[] { maybeLeft }, // ReadMaybeType(Expression.Property(member, eitherLeft), stream, null), // //Expression.IfThen(Expression.Equal(Expression.Property(maybeLeft, maybeVal), Expression.Constant(null)), // ReadMaybeType(Expression.Property(member, eitherRight), stream, null) // //) // ); // return newExpr; //} static BlockExpression ReadAnyType(MemberExpression member, Expression stream, StarSerializeAttribute attrib) { var index = Expression.Property(member, "Index"); var value = Expression.Property(member, "Value"); var types = Expression.Constant(member.Type.GetGenericArguments()); var deserializeMethod = typeof(PacketSerializer).GetMethod("Deserialize", new[] { typeof(StarReader), typeof(Type) }); var indexAsInt = Expression.Decrement(Expression.Convert(index, typeof(int))); var actualType = Expression.ArrayIndex(types, indexAsInt); var body = Expression.Block( Expression.Assign(member, Expression.New(member.Type)), ReadOne(stream, index, typeof(byte), attrib), Expression.IfThen(Expression.Not(Expression.Or( Expression.LessThan(indexAsInt, Expression.Constant(0)), Expression.GreaterThanOrEqual(indexAsInt, Expression.ArrayLength(types)) )), Expression.Assign(value, Expression.Call(deserializeMethod, stream, actualType)))); return(body); }