public DataToString(Type type, IFormatProvider[] providers, char[] delimiters, Func <Type, MemberInfo, int> membersOrder = null) { var typeCount = DataType.IsPrimitiveType(type) ? 1 : DataTypeUtils.GetPublicMembers(type, membersOrder).Count(); if (providers.Length != typeCount) { throw new ArgumentException("providers.Length != dataType.Length"); } Providers = providers; Delimiters = delimiters; Type = type; MembersOrder = membersOrder; LambdaFromString = CreateFromStringMethod(); fromString = LambdaFromString.Compile(); LambdaToString = CreateToStringMethod(); toString = LambdaToString.Compile(); }
public static CompareOption[] GetDefaultCompareOptions(Type type, Func <Type, MemberInfo, int> memberOrder = null) { if (DataType.IsPrimitiveType(type)) { return new CompareOption[] { GetDefaultCompareOption(type) } } ; if (type == typeof(Guid)) { return new CompareOption[] { GetDefaultCompareOption(type) } } ; if (type.IsClass || type.IsStruct()) { return(DataTypeUtils.GetPublicMembers(type, memberOrder).Select(x => GetDefaultCompareOption(x.GetPropertyOrFieldType())).ToArray()); } throw new NotSupportedException(type.ToString()); }
private Expression GetStorePersistCall(IIndexerPersist persist, int slotIndex, Expression msAccess, ParameterExpression values, ParameterExpression count) { var castPersist = Expression.Convert(Expression.Constant(Persists[slotIndex]), Persists[slotIndex].GetType()); var binaryWriter = Expression.New(typeof(BinaryWriter).GetConstructor(new Type[] { typeof(MemoryStream) }), msAccess); var idx = Expression.Variable(typeof(int), "idx"); var callFunc = Expression.Call(values, values.Type.GetMethod("Invoke"), idx); var cast = Expression.Convert(callFunc, DataTypeUtils.GetDataType(DataType)); var field = Expression.Field(cast, String.Format("Slot{0}", slotIndex)); var storeMethod = persist.GetType().GetMethod("Store"); var func = Expression.Lambda(field, idx); var storeCall = Expression.Call(castPersist, storeMethod, new Expression[] { binaryWriter, func, count }); //((IIndexerPersist<Int32>)persist[0]).Store(new BinaryWriter(streams[0]), (idx) => { return ((Data<int, string, double>)values(idx)).Slot0; }, count); return(storeCall); }
public DataToObjects(Type type, Func <Type, MemberInfo, int> membersOrder = null) { if (!DataType.IsPrimitiveType(type) && !type.HasDefaultConstructor()) { throw new NotSupportedException("No default constructor."); } bool isSupported = DataTypeUtils.IsAllPrimitive(type); if (!isSupported) { throw new NotSupportedException("Not all types are primitive."); } Type = type; MembersOrder = membersOrder; LambdaFromObjects = CreateFromObjectsMethod(); fromObjects = LambdaFromObjects.Compile(); LambdaToObjects = CreateToObjectsMethod(); toObjects = LambdaToObjects.Compile(); }
public static Expression CreateComparerBody(List<Expression> expressions, List<ParameterExpression> parameters, Expression x, Expression y, CompareOption[] compareOptions, Func<Type, MemberInfo, int> membersOrder) { var exitPoint = Expression.Label(typeof(int)); List<Expression> list = new List<Expression>(); List<ParameterExpression> variables = new List<ParameterExpression>(); bool haveCmp = false; if (expressions != null) foreach (var expression in expressions) list.Add(expression); if (parameters != null) foreach (var parameter in parameters) variables.Add(parameter); if (DataType.IsPrimitiveType(x.Type) || x.Type == typeof(Guid)) foreach (var command in GetCompareCommands(x, y, Expression.Variable(typeof(int)), exitPoint, x.Type, compareOptions[0], true)) list.Add(command); else { int i = 0; var cmp = Expression.Variable(typeof(int)); foreach (var field in DataTypeUtils.GetPublicMembers(x.Type, membersOrder)) { if (!haveCmp && (field.GetPropertyOrFieldType() == typeof(char) || field.GetPropertyOrFieldType() == typeof(byte[]) || field.GetPropertyOrFieldType() == typeof(Decimal) || field.GetPropertyOrFieldType() == typeof(String))) { haveCmp = true; variables.Add(cmp); } foreach (var command in GetCompareCommands(Expression.PropertyOrField(x, field.Name), Expression.PropertyOrField(y, field.Name), cmp, exitPoint, field.GetPropertyOrFieldType(), compareOptions[i++], i == DataTypeUtils.GetPublicMembers(x.Type, membersOrder).Count())) list.Add(command); } } return Expression.Block(typeof(int), variables, list); }
public static Expression CreateEqualsBody(Expression x, Expression y, CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder) { var type = x.Type; var exitPoint = Expression.Label(typeof(bool)); if (DataType.IsPrimitiveType(type) || type == typeof(Guid)) { return(EqualityComparerHelper.GetEqualsCommand(x, y, compareOptions[0], exitPoint, true)); } else { List <Expression> list = new List <Expression>(); int i = 0; int count = DataTypeUtils.GetPublicMembers(type, membersOrder).Count(); foreach (var member in DataTypeUtils.GetPublicMembers(type, membersOrder)) { list.Add(GetEqualsCommand(Expression.PropertyOrField(x, member.Name), Expression.PropertyOrField(y, member.Name), compareOptions[i++], exitPoint, i == count)); } return(Expression.Block(typeof(bool), list)); } }
internal static Expression CreateStoreBody(Type type, IIndexerPersist[] persists, Expression writer, Expression callValues, ParameterExpression idx, Expression count, Func <Type, MemberInfo, int> membersOrder) { List <Expression> list = new List <Expression>(); int itemsCount = DataTypeUtils.GetPublicMembers(type, membersOrder).Count(); //Create body for single item. if (itemsCount <= 1) { var persist = Expression.Convert(Expression.Constant(persists[0]), persists[0].GetType()); var ms = Expression.Variable(typeof(MemoryStream), "ms"); var func = Expression.Lambda(itemsCount == 0 ? callValues : Expression.PropertyOrField(callValues, DataTypeUtils.GetPublicMembers(type, membersOrder).First().Name), idx); return(ms.Using(Expression.Block( Expression.Assign(ms, Expression.New(typeof(MemoryStream).GetConstructor(new Type[] { }))), Expression.Call(persist, persist.Type.GetMethod("Store"), Expression.New(typeof(BinaryWriter).GetConstructor(new Type[] { typeof(MemoryStream) }), ms), func, count), Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.ConvertChecked(Expression.Property(ms, "Length"), typeof(ulong))), Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(byte[]), typeof(int), typeof(int) }), Expression.Call(ms, typeof(MemoryStream).GetMethod("GetBuffer")), Expression.Constant(0), Expression.Convert(Expression.Property(ms, "Length"), typeof(int))) ))); } else { var streams = Expression.Variable(typeof(MemoryStream[]), "streams"); var actions = Expression.Variable(typeof(Action[]), "actions"); list.Add(Expression.Assign(streams, Expression.New(typeof(MemoryStream[]).GetConstructor(new Type[] { typeof(int) }), Expression.Constant(itemsCount, typeof(int))))); list.Add(Expression.Assign(actions, Expression.New(typeof(Action[]).GetConstructor(new Type[] { typeof(int) }), Expression.Constant(itemsCount, typeof(int))))); int counter = 0; foreach (var member in DataTypeUtils.GetPublicMembers(type, membersOrder)) { var persist = Expression.Convert(Expression.Constant(persists[counter]), persists[counter].GetType()); var ms = Expression.ArrayAccess(streams, Expression.Constant(counter, typeof(int))); var func = Expression.Lambda(Expression.PropertyOrField(callValues, member.Name), idx); var writerNew = Expression.New(typeof(BinaryWriter).GetConstructor(new Type[] { typeof(MemoryStream) }), ms); var action = Expression.Lambda(Expression.Block( Expression.Assign(ms, Expression.New(typeof(MemoryStream).GetConstructor(new Type[] { }))), Expression.Call(persist, persist.Type.GetMethod("Store"), writerNew, func, count) )); list.Add(Expression.Assign(Expression.ArrayAccess(actions, Expression.Constant(counter)), action)); counter++; } list.Add(Expression.Call(typeof(Parallel).GetMethod("Invoke", new Type[] { typeof(Action[]) }), actions)); list.Add(streams.For( (i) => { var stream = Expression.Variable(typeof(MemoryStream), "stream"); return(stream.Using(Expression.Block( Expression.Assign(stream, Expression.ArrayAccess(streams, i)), Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.ConvertChecked(Expression.Property(stream, "Length"), typeof(ulong))), Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(byte[]), typeof(int), typeof(int) }), Expression.Call(stream, typeof(MemoryStream).GetMethod("GetBuffer")), Expression.Constant(0), Expression.Convert(Expression.Property(stream, "Length"), typeof(int))) ))); }, Expression.Label() )); return(Expression.Block(new ParameterExpression[] { actions, streams }, list)); } }
private Expression <Action <BinaryReader, Action <int, IData>, int> > CreateLoadMethod() { List <Expression> list = new List <Expression>(); var reader = Expression.Parameter(typeof(BinaryReader), "reader"); var values = Expression.Parameter(typeof(Action <int, IData>), "values"); var count = Expression.Parameter(typeof(int), "count"); var idataType = DataTypeUtils.GetDataType(DataType); //Data<int, string, double>[] array = new Data<int, string, double>[count]; var array = Expression.Variable(idataType.MakeArrayType(), "array"); var newArray = Expression.NewArrayBounds(idataType, count); var assignArray = Expression.Assign(array, newArray); list.Add(assignArray); //for (int i = 0; i < count; i++) //{ // var data = new Data<int, string, double>(); // array[i] = data; // values(i, data); //} var i = Expression.Variable(typeof(int), "i"); var counterAssign = Expression.Assign(i, Expression.Constant(0)); list.Add(counterAssign); var data = Expression.Variable(idataType, "data"); var callAction = Expression.Call(values, values.Type.GetMethod("Invoke"), i, data); LabelTarget returnPoint = Expression.Label("RETURN_POINT"); var loopBody = Expression.Block(new ParameterExpression[] { data }, Expression.Assign(data, Expression.New(idataType)), Expression.Assign(Expression.ArrayAccess(array, i), data), callAction, Expression.AddAssign(i, Expression.Constant(1)) ); var loop = Expression.Loop(Expression.IfThenElse(Expression.LessThan(i, count), loopBody, Expression.Break(returnPoint)), returnPoint); list.Add(loop); //Action[] actions = new Action[DataType.TypesCount]; var actions = Expression.Variable(typeof(Action[]), "actions"); var newActions = Expression.NewArrayBounds(typeof(Action), Expression.Constant(DataType.TypesCount)); var assignActions = Expression.Assign(actions, newActions); list.Add(assignActions); //byte[][] buffers = new byte[DataType.TypesCount][]; var buffers = Expression.Variable(typeof(byte[][]), "buffers"); var newBuffers = Expression.NewArrayBounds(typeof(byte[]), Expression.Constant(DataType.TypesCount)); var assignBuffers = Expression.Assign(buffers, newBuffers); list.Add(assignBuffers); //for (int j = 0; j < DataType.TypesCount; j++) // buffers[j] = reader.ReadBytes((int)CountCompression.Deserialize(reader)); var counterAssign2 = Expression.Assign(i, Expression.Constant(0)); list.Add(counterAssign2); var ReadBytes = typeof(BinaryReader).GetMethod("ReadBytes", new Type[] { typeof(int) }); var Deserialize = typeof(CountCompression).GetMethod("Deserialize"); var callDeserialize = Expression.Convert(Expression.Call(Deserialize, reader), typeof(int)); var callReadBytes = Expression.Call(reader, ReadBytes, callDeserialize); var loopBody2 = Expression.Block( Expression.Assign(Expression.ArrayAccess(buffers, i), callReadBytes), Expression.AddAssign(i, Expression.Constant(1))); var loop2 = Expression.Loop(Expression.IfThenElse(Expression.LessThan(i, Expression.Constant(DataType.TypesCount, typeof(int))), loopBody2, Expression.Break(returnPoint)), returnPoint); list.Add(loop2); //Int32 //actions[0] = () => //{ // using (MemoryStream ms = new MemoryStream(buffers[0])) // new Int32IndexerPersist().Load(new BinaryReader(ms), (idx, value) => { array[idx].Slot0 = value; }, count); //}; for (int k = 0; k < DataType.TypesCount; k++) { var slotType = idataType.GetField("Slot" + k).FieldType; var loadBody = GetLoadActionBody(slotType, k, array, buffers, values, count); var action = Expression.Assign(Expression.ArrayAccess(actions, Expression.Constant(k)), loadBody); list.Add(action); } //Parallel.Invoke(actions); var Invoke = typeof(Parallel).GetMethod("Invoke", new Type[] { typeof(Action[]) }); list.Add(Expression.Call(Invoke, actions)); var lambdaBody = Expression.Block(new ParameterExpression[] { array, actions, buffers, i }, list); var lambda = Expression.Lambda <Action <BinaryReader, Action <int, IData>, int> >(lambdaBody, new ParameterExpression[] { reader, values, count }); return(lambda); }
public static bool CheckCompatible(Type type1, Type type2, HashSet <Type> cycleCheck, Func <Type, MemberInfo, int> membersOrder1 = null, Func <Type, MemberInfo, int> membersOrder2 = null) { if (type1 == typeof(Guid) || type1 == typeof(byte[])) { return(type2 == typeof(Guid) || type2 == typeof(byte[])); } if (type1.IsEnum || type2.IsEnum) { return((type1.IsEnum && type2.IsEnum) || (IsIntegerType(type1) || IsIntegerType(type2))); } if (DataType.IsPrimitiveType(type1)) { return((type1 == type2) || (IsNumberType(type1) && IsNumberType(type2))); } if (type1.IsArray) { return(CheckCompatible(type1.GetElementType(), type2.GetElementType(), cycleCheck, membersOrder1, membersOrder2)); } if (type1.IsList()) { return(CheckCompatible(type1.GetGenericArguments()[0], type2.GetGenericArguments()[0], cycleCheck, membersOrder1, membersOrder2)); } if (type1.IsDictionary()) { return(CheckCompatible(type1.GetGenericArguments()[0], type2.GetGenericArguments()[0], cycleCheck, membersOrder1, membersOrder2) && CheckCompatible(type1.GetGenericArguments()[1], type2.GetGenericArguments()[1], cycleCheck, membersOrder1, membersOrder2)); } if (type1.IsClass || type1.IsStruct()) { List <Type> type1Slotes = new List <Type>(); List <Type> type2Slotes = new List <Type>(); if (type1.IsNullable()) { type1Slotes.Add(type1.GetGenericArguments()[0]); } if (type2.IsNullable()) { type2Slotes.Add(type2.GetGenericArguments()[0]); } if (type1.IsKeyValuePair()) { type1Slotes.Add(type1.GetGenericArguments()[0]); type1Slotes.Add(type1.GetGenericArguments()[1]); } if (type2.IsKeyValuePair()) { type2Slotes.Add(type2.GetGenericArguments()[0]); type2Slotes.Add(type2.GetGenericArguments()[1]); } foreach (var slote in DataTypeUtils.GetPublicMembers(type1, membersOrder1)) { type1Slotes.Add(slote.GetPropertyOrFieldType()); } foreach (var slote in DataTypeUtils.GetPublicMembers(type2, membersOrder2)) { type2Slotes.Add(slote.GetPropertyOrFieldType()); } if (type1Slotes.Count != type2Slotes.Count) { return(false); } for (int i = 0; i < type1Slotes.Count; i++) { if (cycleCheck.Contains(type1Slotes[i])) { throw new NotSupportedException(String.Format("Type {0} has cycle declaration.", type1Slotes[i])); } cycleCheck.Add(type1Slotes[i]); if (!CheckCompatible(type1Slotes[i], type2Slotes[i], cycleCheck, membersOrder1, membersOrder2)) { return(false); } cycleCheck.Remove(type1Slotes[i]); } return(true); } throw new NotSupportedException(type2.ToString()); }
public static Expression BuildBody(Expression Value1, Expression Value2, Func <Type, MemberInfo, int> membersOrder1, Func <Type, MemberInfo, int> membersOrder2) { var type1 = Value1.Type; var type2 = Value2.Type; if (type1 == typeof(Guid) || type2 == typeof(Guid)) { return(Expression.Assign(Value1, type1 == typeof(Guid) ? Value2.Type == typeof(Guid) ? Value2 : Expression.New(type1.GetConstructor(new Type[] { typeof(byte[]) }), Value2) : Expression.Call(Value2, type2.GetMethod("ToByteArray")) )); } if (type1.IsEnum || type2.IsEnum) { return(Expression.Assign(Value1, Expression.Convert(Value2, type1))); } if (IsEqualsTypes(type1, type2)) { return(Expression.Assign(Value1, Value2)); } if (IsNumberType(type1) && IsNumberType(type2)) { return(Expression.Assign(Value1, Expression.Convert(Value2, type1))); } if (type1.IsKeyValuePair()) { var key = Expression.Variable(type1.GetGenericArguments()[0]); var value = Expression.Variable(type1.GetGenericArguments()[1]); return(Expression.Assign(Value1, Expression.New((typeof(KeyValuePair <,>).MakeGenericType(key.Type, value.Type)).GetConstructor(new Type[] { key.Type, value.Type }), Expression.Block(key.Type, new ParameterExpression[] { key }, BuildBody(key, Expression.PropertyOrField(Value2, type2.IsKeyValuePair() ? "Key" : DataTypeUtils.GetPublicMembers(Value2.Type, membersOrder2).First().Name), membersOrder1, membersOrder2), Expression.Label(Expression.Label(key.Type), key)), Expression.Block(value.Type, new ParameterExpression[] { value }, BuildBody(value, Expression.PropertyOrField(Value2, type2.IsKeyValuePair() ? "Value" : DataTypeUtils.GetPublicMembers(Value2.Type, membersOrder2).Last().Name), membersOrder1, membersOrder2), Expression.Label(Expression.Label(value.Type), value)) ))); } if (type1.IsList() || type1.IsArray) { var element = Expression.Variable(type1.IsArray ? type1.GetElementType() : type1.GetGenericArguments()[0]); var block = Expression.Block(new ParameterExpression[] { element }, Expression.Assign(Value1, Expression.New(Value1.Type.GetConstructor(new Type[] { typeof(int) }), Expression.PropertyOrField(Value2, type2.IsList() ? "Count" : "Length"))), Value2.For(i => { return(type2.IsList() ? (Expression)Expression.Call(Value1, type1.GetMethod("Add"), BuildBody(element, Value2.This(i), membersOrder1, membersOrder2)) : Expression.Assign(Expression.ArrayAccess(Value1, i), BuildBody(element, Expression.ArrayAccess(Value2, i), membersOrder1, membersOrder2))); }, Expression.Label()) ); return(Expression.IfThenElse(Expression.NotEqual(Value2, Expression.Constant(null)), block, Expression.Assign(Value1, Expression.Constant(null, Value1.Type)))); } if (type1.IsDictionary()) { if (!DataType.IsPrimitiveType(type1.GetGenericArguments()[0]) && type1.GetGenericArguments()[0] == typeof(Guid)) { throw new NotSupportedException(String.Format("Dictionary<{0}, TValue>", type1.GetGenericArguments()[0])); } var key = Expression.Variable(type1.GetGenericArguments()[0]); var value = Expression.Variable(type1.GetGenericArguments()[1]); var block = Expression.Block(new ParameterExpression[] { key, value }, Expression.Assign(Value1, type2.GetGenericArguments()[0] == typeof(byte[]) ? Expression.New(type1.GetConstructor(new Type[] { typeof(int), typeof(IEqualityComparer <byte[]>) }), Expression.PropertyOrField(Value2, "Count"), Expression.Field(null, typeof(BigEndianByteArrayEqualityComparer), "Instance")) : Expression.New(type1.GetConstructor(new Type[] { typeof(int) }), Expression.PropertyOrField(Value2, "Count"))), Value2.ForEach(current => Expression.Call(Value1, type1.GetMethod("Add"), BuildBody(key, Expression.Property(current, "Key"), membersOrder1, membersOrder2), BuildBody(value, Expression.Property(current, "Value"), membersOrder1, membersOrder2)), Expression.Label() )); return(Expression.IfThenElse(Expression.NotEqual(Value2, Expression.Constant(null)), block, Expression.Assign(Value1, Expression.Constant(null, Value1.Type)))); } if (type1.IsNullable()) { var data1Var = Expression.Variable(Value1.Type); var data2Var = Expression.Variable(Value2.Type); List <Expression> list = new List <Expression>(); var constructParam = Expression.PropertyOrField(data2Var, type2.IsNullable() ? "Value" : DataTypeUtils.GetPublicMembers(type2, membersOrder2).First().Name); var block = Expression.Block(new ParameterExpression[] { data1Var, data2Var }, Expression.Assign(data2Var, Value2), Expression.Assign(data1Var, Expression.New( type1.GetConstructor(new Type[] { type1.GetGenericArguments()[0] }), constructParam.GetType() == type1.GetGenericArguments()[0] ? (Expression)constructParam : (Expression)Expression.Convert(constructParam, type1.GetGenericArguments()[0]))), Expression.Assign(Value1, data1Var) ); return(Expression.IfThenElse(Expression.NotEqual(Value2, Expression.Constant(null, type2)), block, Expression.Assign(Value1, Expression.Constant(null, type1)) )); } if (type1.IsClass || type1.IsStruct()) { var data1Var = Expression.Variable(Value1.Type); var data2Var = Expression.Variable(Value2.Type); List <Expression> list = new List <Expression>(); list.Add(Expression.Assign(data1Var, Expression.New(data1Var.Type))); List <MemberInfo> members1 = DataTypeUtils.GetPublicMembers(Value1.Type, membersOrder1).ToList(); List <MemberInfo> members2 = new List <MemberInfo>(); if (type2.IsKeyValuePair() || type2.IsNullable()) { if (type2.IsKeyValuePair()) { members2.Add(type2.GetMember("Key")[0]); } members2.Add(type2.GetMember("Value")[0]); } else { members2 = DataTypeUtils.GetPublicMembers(Value2.Type, membersOrder2).ToList(); } for (int i = 0; i < members1.Count; i++) { list.Add(BuildBody(Expression.PropertyOrField(data1Var, members1[i].Name), Expression.PropertyOrField(data2Var, members2[i].Name), membersOrder1, membersOrder2)); } list.Add(Expression.Assign(Value1, data1Var)); if ((type1.IsStruct() || type2.IsStruct()) && !type2.IsNullable()) { list.Insert(0, Expression.Assign(data2Var, Value2)); list.Add(Expression.Label(Expression.Label(Value1.Type), Value1)); return(Expression.Block(type1, new ParameterExpression[] { data1Var, data2Var }, list)); } return(Expression.Block(type1, new ParameterExpression[] { data2Var }, Expression.Assign(data2Var, Value2), Expression.IfThenElse(Expression.NotEqual(data2Var, Expression.Constant(null)), Expression.Block(new ParameterExpression[] { data1Var }, list), Expression.Assign(Value1, Expression.Constant(null, type1))), Expression.Label(Expression.Label(type1), Value1) )); } throw new NotSupportedException(type1.ToString()); }
public static Expression ToObjects(Expression item, Func <Type, MemberInfo, int> membersOrder) { Type[] types = DataType.IsPrimitiveType(item.Type) ? new Type[] { item.Type } : DataTypeUtils.GetPublicMembers(item.Type, membersOrder).Select(x => x.GetPropertyOrFieldType()).ToArray(); if (types.Length == 1) { return(Expression.NewArrayInit(typeof(object), Expression.Convert(item, typeof(object)))); } Expression[] values = new Expression[types.Length]; int i = 0; foreach (var member in DataTypeUtils.GetPublicMembers(item.Type, membersOrder)) { values[i++] = Expression.Convert(Expression.PropertyOrField(item, member.Name), typeof(object)); } return(Expression.NewArrayInit(typeof(object), values)); }
public static Expression CreateParseBody(Expression item, ParameterExpression stringParam, IFormatProvider[] providers, char[] delimiters, Func <Type, MemberInfo, int> membersOrder) { var array = Expression.Variable(typeof(string[]), "array"); if (DataType.IsPrimitiveType(item.Type) || DataTypeUtils.GetPublicMembers(item.Type, membersOrder).Count() == 1) { var member = DataType.IsPrimitiveType(item.Type) ? item : Expression.PropertyOrField(item, DataTypeUtils.GetPublicMembers(item.Type, membersOrder).First().Name); Expression value; if (member.Type == typeof(String)) { value = stringParam; } else if (member.Type == typeof(byte[])) { var hexParse = typeof(StringExtensions).GetMethod("ParseHex", new Type[] { typeof(string) }); value = Expression.Call(hexParse, stringParam); } else if (member.Type == typeof(char)) { var parseMethod = member.Type.GetMethod("Parse", new Type[] { typeof(string) }); value = Expression.Call(parseMethod, stringParam); } else if (member.Type == typeof(bool)) { var parseMethod = member.Type.GetMethod("Parse"); value = Expression.Call(parseMethod, stringParam); } else { var parseMethod = member.Type.GetMethod("Parse", new Type[] { typeof(string), typeof(IFormatProvider) }); value = Expression.Call(parseMethod, stringParam, Expression.Constant(providers[0], typeof(IFormatProvider))); } return(Expression.Assign(member, value)); } List <Expression> list = new List <Expression>(); list.Add(Expression.Assign(array, Expression.Call(stringParam, typeof(string).GetMethod("Split", new Type[] { typeof(char[]) }), new Expression[] { Expression.Constant(delimiters) }))); int i = 0; foreach (var member in DataTypeUtils.GetPublicMembers(item.Type, membersOrder)) { list.Add(GetParseCommand(Expression.PropertyOrField(item, member.Name), i, array, providers[i++])); } return(Expression.Block(new ParameterExpression[] { array }, list)); }
private Expression <Action <BinaryWriter, Func <int, IData>, int> > CreateStoreMethod() { List <Expression> list = new List <Expression>(); var writer = Expression.Parameter(typeof(BinaryWriter), "writer"); var values = Expression.Parameter(typeof(Func <int, IData>), "values"); var count = Expression.Parameter(typeof(int), "count"); var idataType = DataTypeUtils.GetDataType(DataType); //Action[] actions = new Action[DataType.TypesCount]; var actions = Expression.Variable(typeof(Action[]), "actions"); var newActions = Expression.NewArrayBounds(typeof(Action), Expression.Constant(DataType.TypesCount, typeof(int))); var assignActions = Expression.Assign(actions, newActions); list.Add(assignActions); //MemoryStream[] streams = new MemoryStream[DataType.TypesCount]; var streams = Expression.Variable(typeof(MemoryStream[]), "streams"); var newStreams = Expression.NewArrayBounds(typeof(MemoryStream), Expression.Constant(DataType.TypesCount, typeof(int))); var assignStreams = Expression.Assign(streams, newStreams); list.Add(assignStreams); ////Int //actions[0] = () => //{ // ms[0] = new MemoryStream(); // ((IIndexerPersist<Int32>)persist[0]).Store(new BinaryWriter(streams[0]), (idx) => { return ((Data<int, string, double>)values(idx)).Slot0; }, count); //}; for (int j = 0; j < DataType.TypesCount; j++) { //actions[0] = ()=> { task body } var slotType = idataType.GetField("Slot" + j).FieldType; var storeTaskBody = GetStoreActionBody(Persists[j], j, values, count, streams); var taskAssign = Expression.Assign(Expression.ArrayAccess(actions, Expression.Constant(j)), storeTaskBody); list.Add(taskAssign); } //Parallel.Invoke(actions); var InvokeMethod = typeof(Parallel).GetMethod("Invoke", new Type[] { typeof(Action[]) }); list.Add(Expression.Call(InvokeMethod, actions)); //for (int i = 0; i < DataType.TypesCount; i++) //{ // var stream = streams[i]; // using (stream) // { // CountCompression.Serialize(writer, checked((ulong)stream.Length)); // writer.Write(stream.GetBuffer(), 0, (int)stream.Length); // } //} var i = Expression.Variable(typeof(int), "i"); var msIndex = Expression.ArrayAccess(streams, i); var stream = Expression.Variable(typeof(MemoryStream), "stream"); var assignStream = Expression.Assign(stream, msIndex); var streamLength = Expression.Property(stream, "Length"); var writeByteArray = typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(byte[]), typeof(int), typeof(int) }); LabelTarget returnPoint = Expression.Label("RETURN_POINT"); var GetSerialize = Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.ConvertChecked(streamLength, typeof(ulong))); var GetBuffer = Expression.Call(stream, typeof(MemoryStream).GetMethod("GetBuffer")); var GetWrite = Expression.Call(writer, writeByteArray, GetBuffer, Expression.Constant(0), Expression.Convert(streamLength, typeof(int))); var usingBody = Expression.Block(assignStream, GetSerialize, //CountCompression.Serialize(writer, checked((ulong)stream.Length)); GetWrite // writer.Write(stream.GetBuffer(), 0, (int)stream.Length); ); var streamUsing = stream.Using(usingBody); var counterAssign = Expression.Assign(i, Expression.Constant(0)); list.Add(counterAssign); var loopBody = Expression.Block( //assignStream, //var stream = ms[i]; streamUsing, //using (stream) {...} Expression.AddAssign(i, Expression.Constant(1))); var loop = Expression.Loop(Expression.IfThenElse(Expression.LessThan(i, Expression.Constant(DataType.TypesCount, typeof(int))), loopBody, Expression.Break(returnPoint)), returnPoint); list.Add(loop); var lambdaBody = Expression.Block(new ParameterExpression[] { actions, i, streams }, list); var lambda = Expression.Lambda <Action <BinaryWriter, Func <int, IData>, int> >(lambdaBody, new ParameterExpression[] { writer, values, count }); return(lambda); }
public static Expression CreateToStringBody(Expression item, int stringBuilderCapacity, IFormatProvider[] providers, char delimiter, Func <Type, MemberInfo, int> membersOrder) { var stringBuilder = Expression.Variable(typeof(StringBuilder)); if (DataType.IsPrimitiveType(item.Type) || DataTypeUtils.GetPublicMembers(item.Type, membersOrder).Count() == 1) { var member = DataType.IsPrimitiveType(item.Type) ? item : Expression.PropertyOrField(item, DataTypeUtils.GetPublicMembers(item.Type, membersOrder).First().Name); MethodCallExpression callToString; if (member.Type == typeof(byte[])) { var toHexMethod = typeof(ByteArrayExtensions).GetMethod("ToHex", new Type[] { typeof(byte[]) }); callToString = Expression.Call(toHexMethod, member); } else if (member.Type == typeof(TimeSpan)) { var toStringProvider = member.Type.GetMethod("ToString", new Type[] { typeof(String), typeof(IFormatProvider) }); callToString = Expression.Call(member, toStringProvider, Expression.Constant(null, typeof(String)), Expression.Constant(providers[0], typeof(IFormatProvider))); } else { var toStringProvider = member.Type.GetMethod("ToString", new Type[] { typeof(IFormatProvider) }); callToString = Expression.Call(member, toStringProvider, Expression.Constant(providers[0], typeof(IFormatProvider))); } return(Expression.Label(Expression.Label(typeof(string)), member.Type == typeof(string) ? (Expression)member : (Expression)callToString)); } List <Expression> list = new List <Expression>(); list.Add(Expression.Assign(stringBuilder, Expression.New(stringBuilder.Type.GetConstructor(new Type[] { typeof(int) }), Expression.Constant(stringBuilderCapacity)))); int i = 0; foreach (var member in DataTypeUtils.GetPublicMembers(item.Type, membersOrder)) { list.Add(GetAppendCommand(Expression.PropertyOrField(item, member.Name), stringBuilder, providers[i])); if (i < DataTypeUtils.GetPublicMembers(item.Type, membersOrder).Count() - 1) { list.Add(Expression.Call(stringBuilder, typeof(StringBuilder).GetMethod("Append", new Type[] { typeof(char) }), Expression.Constant(delimiter))); } i++; } list.Add(Expression.Label(Expression.Label(typeof(string)), Expression.Call(stringBuilder, typeof(object).GetMethod("ToString")))); return(Expression.Block(new ParameterExpression[] { stringBuilder }, list)); }
private static Expression BuildWrite(Expression item, Expression writer, Func <Type, MemberInfo, int> membersOrder, AllowNull allowNull, bool isTop) { var type = item.Type; bool canBeNull = allowNull == AllowNull.All || (allowNull == AllowNull.OnlyMembers && !isTop); if (type == typeof(Guid)) { return(GetWriteCommand(writer, Expression.Call(item, type.GetMethod("ToByteArray")), false)); } if (type.IsEnum) { return(GetWriteCommand(writer, Expression.Convert(item, item.Type.GetEnumUnderlyingType()), canBeNull)); } if (DataType.IsPrimitiveType(type)) { return(GetWriteCommand(writer, item, canBeNull)); } if (type.IsKeyValuePair()) { return(Expression.Block( BuildWrite(Expression.PropertyOrField(item, "Key"), writer, membersOrder, allowNull, false), BuildWrite(Expression.PropertyOrField(item, "Value"), writer, membersOrder, allowNull, false) )); } if (type.IsArray || type.IsList()) { if (!canBeNull) { return(Expression.Block(Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.Convert(type.IsArray ? (Expression)Expression.ArrayLength(item) : Expression.Property(item, "Count"), typeof(ulong))), item.For(i => WriteAssignedOrCurrentVariable(type.IsArray ? Expression.ArrayAccess(item, i) : item.This(i), writer, membersOrder, allowNull), Expression.Label()))); } return(Expression.IfThenElse(Expression.NotEqual(item, Expression.Constant(null)), Expression.Block( Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(true)), Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.Convert(type.IsArray ? (Expression)Expression.ArrayLength(item) : Expression.Property(item, "Count"), typeof(ulong))), item.For(i => WriteAssignedOrCurrentVariable(type.IsArray ? Expression.ArrayAccess(item, i) : item.This(i), writer, membersOrder, allowNull), Expression.Label())), Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(false)) )); } if (type.IsDictionary()) { if (!DataType.IsPrimitiveType(type.GetGenericArguments()[0]) && !type.GetGenericArguments()[0].IsEnum && type != typeof(Guid)) { throw new NotSupportedException(String.Format("Dictionarty<{0}, TValue>", type.GetGenericArguments()[0].ToString())); } if (!canBeNull) { return(Expression.Block( Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.Convert(Expression.Property(item, "Count"), typeof(ulong))), item.ForEach(current => { var kv = Expression.Variable(current.Type); return Expression.Block(new ParameterExpression[] { kv }, Expression.Assign(kv, current), WriteAssignedOrCurrentVariable(Expression.PropertyOrField(kv, "Key"), writer, membersOrder, allowNull), WriteAssignedOrCurrentVariable(Expression.PropertyOrField(kv, "Value"), writer, membersOrder, allowNull) ); }, Expression.Label()) )); } return(Expression.IfThenElse(Expression.NotEqual(item, Expression.Constant(null)), Expression.Block( Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(true)), Expression.Call(typeof(CountCompression).GetMethod("Serialize"), writer, Expression.Convert(Expression.Property(item, "Count"), typeof(ulong))), item.ForEach(current => { var kv = Expression.Variable(current.Type); return Expression.Block(new ParameterExpression[] { kv }, Expression.Assign(kv, current), WriteAssignedOrCurrentVariable(Expression.PropertyOrField(kv, "Key"), writer, membersOrder, allowNull), WriteAssignedOrCurrentVariable(Expression.PropertyOrField(kv, "Value"), writer, membersOrder, allowNull) ); }, Expression.Label())), Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(false)) )); } if (type.IsNullable()) { if (!canBeNull) { return(BuildWrite(Expression.PropertyOrField(item, "Value"), writer, membersOrder, allowNull, false)); } return(Expression.Block(Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.PropertyOrField(item, "HasValue")), Expression.IfThen(Expression.PropertyOrField(item, "HasValue"), BuildWrite(Expression.PropertyOrField(item, "Value"), writer, membersOrder, allowNull, false)))); } if (type.IsClass || type.IsStruct()) { List <ParameterExpression> variables = new List <ParameterExpression>(); List <Expression> list = new List <Expression>(); if (canBeNull && !type.IsStruct()) { list.Add(Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(true))); } foreach (var member in DataTypeUtils.GetPublicMembers(type, membersOrder)) { if (DataType.IsPrimitiveType(type) || type.IsKeyValuePair()) { list.Add(BuildWrite(Expression.PropertyOrField(item, member.Name), writer, membersOrder, allowNull, false)); } else { var @var = Expression.Variable(member.GetPropertyOrFieldType()); variables.Add(var); list.Add(Expression.Assign(var, Expression.PropertyOrField(item, member.Name))); list.Add(BuildWrite(var, writer, membersOrder, allowNull, false)); } } if (!canBeNull || type.IsStruct()) { return(Expression.Block(variables, list)); } return(Expression.IfThenElse(Expression.NotEqual(item, Expression.Constant(null)), Expression.Block(variables, list), Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(false)) )); } throw new NotSupportedException(item.Type.ToString()); }
private Expression <Action <BinaryWriter, Func <int, IData>, int> > CreateStoreMethodSingleSlot() { var writer = Expression.Parameter(typeof(BinaryWriter), "writer"); var values = Expression.Parameter(typeof(Func <int, IData>), "values"); var count = Expression.Parameter(typeof(int), "count"); var idataType = DataTypeUtils.GetDataType(DataType); List <Expression> list = new List <Expression>(); //MemoryStream ms = new MemoryStream() var ms = Expression.Variable(typeof(MemoryStream), "ms"); var newMs = Expression.New(typeof(MemoryStream).GetConstructor(new Type[] { })); var msLength = Expression.Property(ms, "Length"); //((IIndexerPersist<Int32>)persist[0]).Store(new BinaryWriter(streams[0]), (idx) => { return ((Data<int, string, double>)values(idx)).Slot0; }, count); var castPersist = Expression.Convert(Expression.Constant(Persists[0]), Persists[0].GetType()); var storeMethod = Persists[0].GetType().GetMethod("Store"); var binaryWriter = Expression.New(typeof(BinaryWriter).GetConstructor(new Type[] { typeof(MemoryStream) }), ms); var idx = Expression.Variable(typeof(int), "idx"); var internalCall = Expression.Call(values, values.Type.GetMethod("Invoke"), idx); var cast = Expression.Convert(internalCall, idataType); var field = Expression.Field(cast, String.Format("Slot{0}", 0)); var func = Expression.Lambda(field, idx); var storeCall = Expression.Call(castPersist, storeMethod, new Expression[] { binaryWriter, func, count }); list.Add(storeCall); //CountCompression.Serialize(writer, checked((ulong)ms.Length)); var callCompression = Expression.Call(typeof(CountCompression), "Serialize", null, new Expression[] { writer, Expression.ConvertChecked(msLength, typeof(ulong)) }); list.Add(callCompression); //writer.Write(ms.GetBuffer(), 0, (int)ms.Length); var writeByteArray = typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(byte[]), typeof(int), typeof(int) }); var GetBufferCaller = Expression.Call(ms, typeof(MemoryStream).GetMethod("GetBuffer")); var GetWriteCaller = Expression.Call(writer, writeByteArray, GetBufferCaller, Expression.Constant(0), Expression.Convert(msLength, typeof(int))); list.AddRange(new Expression[] { GetWriteCaller }); //using (MemoryStream ms = new MemoryStream()) //{ // ((IIndexerPersist<String>)persist[0]).Store(new BinaryWriter(ms), (idx) => { return ((Data<string>)values(idx)).Slot0; }, count); // CountCompression.Serialize(writer, checked((ulong)ms.Length)); // writer.Write(ms.GetBuffer(), 0, (int)ms.Length); //} var usingBody = Expression.Block(list); var methodbody = ms.Using(newMs, usingBody); var parameters = new ParameterExpression[] { writer, values, count }; var lambda = Expression.Lambda <Action <BinaryWriter, Func <int, IData>, int> >(methodbody, parameters); return(lambda); }
public static Expression FromObjects(Expression item, ParameterExpression objectArray, Func <Type, MemberInfo, int> membersOrder) { Type[] types = DataType.IsPrimitiveType(item.Type) ? new Type[] { item.Type } : DataTypeUtils.GetPublicMembers(item.Type, membersOrder).Select(x => x.GetPropertyOrFieldType()).ToArray(); if (types.Length == 1) { return(Expression.Assign(item, Expression.Convert(Expression.ArrayAccess(objectArray, Expression.Constant(0, typeof(int))), types[0]))); } List <Expression> list = new List <Expression>(); int i = 0; foreach (var member in DataTypeUtils.GetPublicMembers(item.Type, membersOrder)) { list.Add(Expression.Assign(Expression.PropertyOrField(item, member.Name), Expression.Convert(Expression.ArrayAccess(objectArray, Expression.Constant(i, typeof(int))), types[i++]))); } return(Expression.Block(list)); }
private static Expression BuildRead(Expression reader, Type itemType, Func <Type, MemberInfo, int> membersOrder, AllowNull allowNull, bool isTop) { bool canBeNull = allowNull == AllowNull.All || (allowNull == AllowNull.OnlyMembers && !isTop); if (itemType == typeof(Guid)) { return(Expression.New(itemType.GetConstructor(new Type[] { typeof(byte[]) }), GetReadCommand(reader, typeof(byte[]), false))); } if (itemType.IsEnum) { return(Expression.Convert(GetReadCommand(reader, itemType.GetEnumUnderlyingType(), canBeNull), itemType)); } if (DataType.IsPrimitiveType(itemType)) { return(GetReadCommand(reader, itemType, canBeNull)); } if (itemType.IsKeyValuePair()) { return(Expression.New( itemType.GetConstructor(new Type[] { itemType.GetGenericArguments()[0], itemType.GetGenericArguments()[1] }), BuildRead(reader, itemType.GetGenericArguments()[0], membersOrder, allowNull, false), BuildRead(reader, itemType.GetGenericArguments()[1], membersOrder, allowNull, false) )); } if (itemType.IsArray || itemType.IsList() || itemType.IsDictionary()) { var field = Expression.Variable(itemType); var lenght = Expression.Variable(typeof(int)); var block = Expression.Block( Expression.Assign(lenght, Expression.Convert(Expression.Call(typeof(CountCompression).GetMethod("Deserialize"), reader), typeof(int))), itemType.IsDictionary() && itemType.GetGenericArguments()[0] == typeof(byte[]) ? Expression.Assign(field, Expression.New(field.Type.GetConstructor(new Type[] { typeof(int), typeof(IEqualityComparer <byte[]>) }), lenght, Expression.Field(null, typeof(BigEndianByteArrayEqualityComparer), "Instance"))) : Expression.Assign(field, Expression.New(field.Type.GetConstructor(new Type[] { typeof(int) }), lenght)), field.For(i => { if (itemType.IsArray) { return(Expression.Assign(Expression.ArrayAccess(field, i), BuildRead(reader, itemType.GetElementType(), membersOrder, allowNull, false))); } else if (itemType.IsList()) { return(Expression.Call(field, field.Type.GetMethod("Add"), BuildRead(reader, itemType.GetGenericArguments()[0], membersOrder, allowNull, false))); } else //if (dataType.IsDictionary) { return(Expression.Call(field, field.Type.GetMethod("Add"), BuildRead(reader, itemType.GetGenericArguments()[0], membersOrder, allowNull, false), BuildRead(reader, itemType.GetGenericArguments()[1], membersOrder, allowNull, false) )); } }, Expression.Label(), lenght) ); if (canBeNull) { return(Expression.Block(field.Type, new ParameterExpression[] { field, lenght }, Expression.IfThenElse(Expression.Call(reader, typeof(BinaryReader).GetMethod("ReadBoolean")), block, Expression.Assign(field, Expression.Constant(null, field.Type))), Expression.Label(Expression.Label(field.Type), field))); } return(Expression.Block(field.Type, new ParameterExpression[] { field, lenght }, block, Expression.Label(Expression.Label(field.Type), field))); } if (itemType.IsNullable()) { if (!canBeNull) { return(Expression.New(itemType.GetConstructor(new Type[] { itemType.GetGenericArguments()[0] }), BuildRead(reader, itemType.GetGenericArguments()[0], membersOrder, allowNull, false))); } return(Expression.Condition(Expression.Call(reader, typeof(BinaryReader).GetMethod("ReadBoolean")), Expression.New(itemType.GetConstructor(new Type[] { itemType.GetGenericArguments()[0] }), BuildRead(reader, itemType.GetGenericArguments()[0], membersOrder, allowNull, false)), Expression.Constant(null, itemType))); } if (itemType.IsClass || itemType.IsStruct()) { var item = Expression.Variable(itemType); List <Expression> list = new List <Expression>(); list.Add(Expression.Assign(item, Expression.New(item.Type))); foreach (var member in DataTypeUtils.GetPublicMembers(itemType, membersOrder)) { list.Add(Expression.Assign(Expression.PropertyOrField(item, member.Name), BuildRead(reader, member.GetPropertyOrFieldType(), membersOrder, allowNull, false))); } if (!canBeNull || itemType.IsStruct()) { list.Add(Expression.Label(Expression.Label(item.Type), item)); return(Expression.Block(item.Type, new ParameterExpression[] { item }, list)); } return(Expression.Block(itemType, new ParameterExpression[] { item }, Expression.IfThenElse(Expression.Call(reader, typeof(BinaryReader).GetMethod("ReadBoolean")), Expression.Block(list), Expression.Assign(item, Expression.Constant(null, itemType))), Expression.Label(Expression.Label(item.Type), item))); } throw new ArgumentException(itemType.ToString()); }
private IEnumerable <MemberInfo> GetPublicMembers(Type type) { return(DataTypeUtils.GetPublicMembers(type, MembersOrder)); }