Expression Value(IParser parser, Expression valueType, RuntimeSchema schema) { Debug.Assert(schema.HasValue); if (parser.IsBonded || (untaggedWriter && schema.IsBonded)) { return(parser.Bonded(value => writer.WriteBonded(PrunedExpression.Convert(value, typeof(IBonded))))); } if (schema.IsStruct) { return(GenerateSerialize(Struct, parser, schema)); } if (schema.IsMap) { return(GenerateSerialize(Map, parser, schema)); } if (schema.IsContainer) { return(GenerateSerialize(Container, parser, schema)); } return(parser.Scalar(valueType, schema.TypeDef.id, value => writer.Write(value, schema.TypeDef.id))); }
Expression Value(IParser parser, Expression valueType) { if (parser.IsBonded) { return(parser.Bonded(value => writer.WriteBonded(PrunedExpression.Convert(value, typeof(IBonded))))); } var switchCases = new List <DeferredSwitchCase> { PrunedExpression.SwitchCase( () => GenerateSerialize(Container, parser), BondDataType.BT_LIST, BondDataType.BT_SET), PrunedExpression.SwitchCase( () => GenerateSerialize(Map, parser), BondDataType.BT_MAP), PrunedExpression.SwitchCase( () => GenerateSerialize(Struct, parser), BondDataType.BT_STRUCT) }; switchCases.AddRange( from type in new[] { BondDataType.BT_BOOL, BondDataType.BT_UINT8, BondDataType.BT_UINT16, BondDataType.BT_UINT32, BondDataType.BT_UINT64, BondDataType.BT_FLOAT, BondDataType.BT_DOUBLE, BondDataType.BT_STRING, BondDataType.BT_INT8, BondDataType.BT_INT16, BondDataType.BT_INT32, BondDataType.BT_INT64, BondDataType.BT_WSTRING } select PrunedExpression.SwitchCase( () => parser.Scalar(Expression.Constant(type), type, value => writer.Write(value, type)), type)); return(PrunedExpression.Switch( valueType, ThrowExpression.InvalidTypeException(valueType), switchCases)); }
public Expression Assign(Expression left, Expression right) { var leftType = left.Type; if (leftType != right.Type && leftType.IsGenericType() && leftType.GetGenericTypeDefinition() == typeof(Nullable <>)) { leftType = leftType.GetGenericArguments()[0]; } var value = Convert(right, leftType); return(Expression.Assign(left, PrunedExpression.Convert(value, left.Type))); }
/// <summary> /// Generate expression provided by Serialize delegate, either as inline expression or a lambda call /// </summary> /// <param name="serialize">Delegate to generate serialization expression</param> /// <param name="parser">Parser used for the source of serialization</param> /// <param name="writer">Writer to use for serialization</param> /// <param name="inline">True if the expression can be inlined</param> /// <remarks> /// Generates lambda calls for recursive schemas to avoid infinitely inlining the same expression. /// Expression is considered the same when both serialize delegate and parser are the same. It is /// caller's responsibility to assure that the pair of serialize delegate and parser can be used /// to identify generated expression. For object serializer, when the parser is ObjectParser, this /// is generally guaranteed by using parser instance per schema type. Transcoding may use a single /// parser instance but different Serialize delegates for each transcoded schema type (e.g. when /// the delegate captures schema metadata). /// </remarks> protected Expression GenerateSerialize(Serialize serialize, IParser parser, ParameterExpression writer, bool inline) { var key = new KeyValuePair <IParser, Serialize>(parser, serialize); inline = inline && inProgress.Count != 0 && !inProgress.Contains(key); Expression body; inProgress.Push(key); if (inline) { body = serialize(parser); if (parser.ReaderParam != parser.ReaderValue && parser.ReaderValue.Type.IsBondStruct()) { body = Expression.Block( new[] { parser.ReaderParam }, Expression.Assign(parser.ReaderParam, Expression.Convert(parser.ReaderValue, parser.ReaderParam.Type)), body); } } else { int index; if (!serializeIndex.TryGetValue(key, out index)) { index = serializeActions.Count; serializeIndex[key] = index; serializeActions.Add(null); serializeActions[index] = Expression.Lambda <Action <R, W> >( serialize(parser), parser.ReaderParam, writer); } body = Expression.Invoke( deferredSerialize, PrunedExpression.Convert(parser.ReaderValue, parser.ReaderParam.Type), writer, Expression.Constant(index)); } inProgress.Pop(); return(body); }
Expression Value(IParser parser, Expression var, Expression valueType, Type schemaType, bool initialize) { if (schemaType.IsBondNullable()) { return(Nullable(parser, var, schemaType.GetValueType(), initialize)); } if (schemaType.IsBonded()) { var convert = bondedConvert.MakeGenericMethod(var.Type.GetValueType()); return(parser.Bonded(value => Expression.Assign(var, Expression.Call(value, convert)))); } if (schemaType.IsBondStruct()) { if (parser.IsBonded) { var deserialize = bondedDeserialize.MakeGenericMethod(schemaType); return(parser.Bonded(value => Expression.Assign(var, Expression.Call(value, deserialize)))); } return(Deserialize(parser, var, var.Type, schemaType, initialize)); } if (schemaType.IsBondMap()) { return(Map(parser, var, schemaType, initialize)); } if (schemaType.IsBondContainer()) { return(Container(parser, var, schemaType, initialize)); } return(parser.Scalar(valueType, schemaType.GetBondDataType(), value => typeAlias.Assign(var, PrunedExpression.Convert(value, schemaType)))); }
public Expression Assign(Expression left, Expression right) { var value = Convert(right, left.Type); return(Expression.Assign(left, PrunedExpression.Convert(value, left.Type))); }