private Expression ListSerializer(Expression injectedPacket, Expression specificTypeExpression, PacketIndexAttribute indexAttr, Type type, string packetSplitter, Expression propertySplitter) { var subtype = type.GenericTypeArguments.Any() ? type.GenericTypeArguments[0] : type.GetElementType(); var param = Expression.Parameter(subtype); var isPacketList = false; if (typeof(IPacket).IsAssignableFrom(subtype)) { indexAttr.IsOptional = false; isPacketList = true; } var selectExp = Expression.Call( typeof(Enumerable), "Select", new[] { subtype, typeof(string) }, specificTypeExpression, Expression.Lambda( Expression.Convert(isPacketList ? IPacketSerializer(injectedPacket, indexAttr, param, subtype, 0, propertySplitter, "", true) : PropertySerializer(injectedPacket, indexAttr, subtype, param, 0, Expression.Constant("")), typeof(string)), param) ); var listJoin = Expression.Convert(Expression.Call( typeof(string).GetMethod("Join", new[] { typeof(string), typeof(IEnumerable <string>) }), isPacketList ? Expression.Constant(packetSplitter, typeof(string)) : propertySplitter, selectExp), typeof(object)); return(Expression.Condition( Expression.Equal(specificTypeExpression, Expression.Constant(null, typeof(object))), Expression.Constant(null, typeof(object)), ConcatExpression(Expression.Constant(indexAttr.SpecialSeparator != null ? " " : string.Empty), Expression.Convert(listJoin, typeof(object))) )); }
private object DeserializeList(Type subType, PacketIndexAttribute packetIndexAttribute, Match[] matches, ref int currentIndex, bool isMaxIndex) { int newIndex = currentIndex; var length = packetIndexAttribute.Length; string[] splited = null; if (length == -1) { length = sbyte.Parse(matches[currentIndex - 1].Value); } else { if (isMaxIndex && string.IsNullOrEmpty(packetIndexAttribute.SpecialSeparator)) { length = (sbyte)(matches.Length - currentIndex); } if (!string.IsNullOrEmpty(packetIndexAttribute.SpecialSeparator)) { splited = matches[currentIndex].Value.Split(new string[] { packetIndexAttribute.SpecialSeparator }, StringSplitOptions.None); length = (sbyte)splited.Length; } } if (length > 0) { var list = new List <object>(); for (var i = 0; i < length; i++) { if (typeof(IPacket).IsAssignableFrom(subType)) { var dic = packetDeserializerDictionary.Values.FirstOrDefault(s => s.PacketType == subType); if (dic == null) { continue; } string toConvert; if (matches[currentIndex + i].ToString().Contains(packetIndexAttribute.SpecialSeparator ?? ".")) { toConvert = matches[currentIndex + i].ToString().Replace(packetIndexAttribute.SpecialSeparator ?? ".", " "); } else { toConvert = string.Join(" ", matches.Skip(currentIndex + i * (1 + dic.PropertyAmount)).Take(dic.PropertyAmount + 1)); } list.Add(Convert.ChangeType(DeserializeIPacket(dic, toConvert, false, false), subType)); if (splited == null) { newIndex += 1 + dic.PropertyAmount; } } else //simple list { var value = long.Parse(splited != null ? splited[i] : matches[currentIndex + i].Value); list.Add(Convert.ChangeType(value, subType)); if (splited == null) { newIndex += i + 1; } } } if (splited != null) { newIndex++; } currentIndex = newIndex; return(subType.GetAndFillListMethod()(list)); } return(null); }
private Expression PropertySerializer(Expression injectedPacket, PacketIndexAttribute indexAttr, Type type, Expression specificTypeExpression, int maxIndex, Expression propertySplitter) { var useCustomSerializer = true; switch (type) { //handle boolean case var t when(t == typeof(bool)) || (t == typeof(bool?)): specificTypeExpression = BooleanSerializer(specificTypeExpression, propertySplitter); break; //handle enum case var t when(t.BaseType?.Equals(typeof(Enum)) ?? false) || (Nullable.GetUnderlyingType(t)?.IsEnum ?? false): specificTypeExpression = EnumSerializer(specificTypeExpression, propertySplitter); break; //handle list case var t when t.GetInterface("System.Collections.ICollection") != null: specificTypeExpression = ListSerializer(injectedPacket, specificTypeExpression, indexAttr, t, " ", Expression.Constant(typeof(IPacket).IsAssignableFrom(t.GenericTypeArguments.Any() ? t.GenericTypeArguments[0] : t.GetElementType()) ? indexAttr.SpecialSeparator ?? "." : indexAttr.SpecialSeparator ?? " ")); break; //handle string case var t when t == typeof(string): specificTypeExpression = StringSerializer(specificTypeExpression, indexAttr.Index == maxIndex, indexAttr.IsOptional, propertySplitter); break; //IPacket declared type case var t when typeof(IPacket).IsAssignableFrom(t) && (t != typeof(IPacket)): var header = specificTypeExpression.Type.GetCustomAttribute <PacketHeaderAttribute>() ?.Identification; propertySplitter = Expression.Constant(indexAttr.SpecialSeparator ?? (header == null ? " " : ".")); if (!string.IsNullOrEmpty(header)) { header = $"#{header}"; propertySplitter = Expression.Constant(indexAttr.SpecialSeparator ?? "^"); } if (header == null && indexAttr.SpecialSeparator != null) { header = " "; } specificTypeExpression = IPacketSerializer(injectedPacket, indexAttr, specificTypeExpression, t, maxIndex, propertySplitter, indexAttr.RemoveHeader ? "" : header); break; case var t when t == typeof(IPacket): specificTypeExpression = Expression.Constant(INJECTION_KEY, typeof(string)); break; default: useCustomSerializer = false; break; } if ((type != typeof(string)) && (Nullable.GetUnderlyingType(type) != null)) { specificTypeExpression = NullableSerializer(specificTypeExpression, indexAttr.IsOptional, propertySplitter); useCustomSerializer = true; } if (!useCustomSerializer) { specificTypeExpression = DefaultSerializer(specificTypeExpression, propertySplitter); } return(specificTypeExpression); }
private Expression IPacketSerializer(Expression injectedPacket, PacketIndexAttribute indexAttr, Expression specificTypeExpression, Type prop, int maxIndex, Expression propertySplitter, string discriminator, bool isFromList = false) { var properties = prop.GetProperties() .Where(x => x.GetCustomAttributes(true).OfType <PacketIndexAttribute>().Any()) .OrderBy(x => x.GetCustomAttributes(true).OfType <PacketIndexAttribute>().First().Index).ToList(); Expression propExp = Expression.Condition(injectedPacket, Expression.Constant($"#{discriminator}"), Expression.Constant(discriminator, typeof(string))); Expression incrementExpr = Expression.Condition( Expression.Equal(propertySplitter, Expression.Constant(" ", typeof(string))), Expression.Constant(!string.IsNullOrWhiteSpace(discriminator)), Expression.Constant(false)); var startserie = true; var isOptionalSerie = false; foreach (var property in properties) { var index = property.GetCustomAttributes(true).OfType <PacketIndexAttribute>().First(); if (startserie && index.IsOptional) { isOptionalSerie = true; } else { startserie = index.IsOptional; isOptionalSerie = false; } var exp = Expression.Convert( PropertySerializer(injectedPacket, index, property.PropertyType, Expression.Property(specificTypeExpression, property.Name), maxIndex, Expression.Condition(injectedPacket, Expression.Constant("^", typeof(object)), Expression.Constant(index.SpecialSeparator, typeof(object)))) , typeof(object)); var splitter = Expression.Condition(injectedPacket, Expression.Constant(string.Empty, typeof(object)), index.SpecialSeparator != null ? Expression.Constant(indexAttr.SpecialSeparator ?? string.Empty, typeof(object)) : (Expression)Expression.Convert(propertySplitter, typeof(object))); var trimfirst = Expression.Condition( Expression.Equal(incrementExpr, Expression.Constant(false)), exp, ConcatExpression(splitter, exp)); var trimnull = Expression.Condition( Expression.Equal(exp, Expression.Constant(null, typeof(string))), Expression.Constant(string.Empty, typeof(object)), trimfirst); propExp = ConcatExpression(propExp, trimnull); incrementExpr = Expression.Constant(!isFromList || !isOptionalSerie); } return(Expression.Condition( Expression.Equal(specificTypeExpression, Expression.Constant(null, typeof(object))), Expression.Constant(indexAttr.IsOptional ? null : "-1", typeof(object)), Expression.Convert(propExp, typeof(object)) )); }