public DataToStringTransformer(DataType dataType, IFormatProvider[] providers, char[] delimiters) { bool supported = dataType.IsPrimitive || (dataType.IsSlotes && dataType.AreAllTypesPrimitive); if (!supported) { throw new NotSupportedException(dataType.ToString()); } if (dataType.IsPrimitive && providers.Length != 1) { throw new ArgumentException("providers"); } if (dataType.IsSlotes && providers.Length != dataType.TypesCount) { throw new ArgumentException("providers"); } DataType = dataType; Providers = providers; Delimiters = delimiters; Type = DataTypeUtils.GetDataType(dataType); //prepare toIData LambdaToIData = CreateToIDataMethod(); toIData = LambdaToIData.Compile(); //prepare fromIData LambdaFromIData = CreateFromIDataMethod(); fromIData = LambdaFromIData.Compile(); }
/// <summary> /// /// </summary> /// <param name="membersOrder">Defines the declaration order of each property and field (because it is not guaranteed by the typeof(T).GetMembers() method)</param> public DataTransformer(Func <Type, MemberInfo, int> membersOrder) { if (!DataType.IsPrimitiveType(typeof(T)) && typeof(T).IsClass && typeof(T).GetConstructor(new Type[] { }) == null) { throw new NotSupportedException(String.Format("Type '{0}' does not have a default constructor", typeof(T))); } MembersOrder = membersOrder; List <Type> list = new List <Type>(); BuildSlotTypes(list, typeof(T), new HashSet <Type>()); slotTypes = list.ToArray(); if (slotTypes.Length == 0) { throw new ArgumentException(String.Format("No public read/write properties/fields available for mapping.")); } Type = DataTypeUtils.GetDataType(slotTypes); DataType = DataTypeUtils.FromPrimitiveTypes(slotTypes); LambdaToIData = CreateToIDataMethod(); toIData = LambdaToIData.Compile(); LambdaFromIData = CreateFromIDataMethod(); fromIData = LambdaFromIData.Compile(); }
private Expression <Func <IData, int> > CreateGetHashCodeMethod() { var obj = Expression.Parameter(typeof(IData), "obj"); var idataType = DataTypeUtils.GetDataType(DataType); var x = Expression.Variable(idataType, "x"); var assign1 = Expression.Assign(x, Expression.Convert(obj, idataType)); Expression[] values = new Expression[DataType.IsPrimitive ? 1 : DataType.TypesCount]; if (DataType.IsPrimitive) { values[0] = GetHashCodeCommand(x, DataType, 0); } else { for (int i = 0; i < DataType.TypesCount; i++) { values[i] = GetHashCodeCommand(x, DataType[i], i); } } var result = Expression.Variable(typeof(int), "result"); var xor = values[0]; if (DataType.IsSlotes) { for (int i = 1; i < DataType.TypesCount; i++) { xor = Expression.ExclusiveOr(xor, values[i]); } } var assign2 = Expression.Assign(result, xor); List <Expression> list = new List <Expression>(); var exitPoint = Expression.Label(typeof(int)); list.Add(assign1); list.Add(assign2); list.Add(Expression.Label(exitPoint, result)); var body = Expression.Block(typeof(int), new ParameterExpression[] { x, result }, list); var lambda = Expression.Lambda <Func <IData, int> >(body, obj); //public int GetHashCode(IData obj) //{ // var x = (Data<byte[], string, double>)obj; // return BigEndianByteArrayEqualityComparer.Instance.GetHashCode(x.Slot0) ^ x.Slot1.GetHashCode() ^ x.Slot2.GetHashCode(); //} return(lambda); }
public Expression <Action <BinaryReader, Action <int, IData>, int> > CreateLoadMethodSingleSlot() { var reader = Expression.Parameter(typeof(BinaryReader), "reader"); var values = Expression.Parameter(typeof(Action <int, IData>), "values"); var count = Expression.Parameter(typeof(int), "count"); List <Expression> list = new List <Expression>(); //byte[] buffer = reader.ReadBytes((int)CountCompression.Deserialize(reader)); var buffer = Expression.Variable(typeof(byte[]), "buffer"); var ReadBytes = typeof(BinaryReader).GetMethod("ReadBytes"); var counter = Expression.Convert(Expression.Call(typeof(CountCompression).GetMethod("Deserialize"), reader), typeof(int)); var ReadBytesCaller = Expression.Call(reader, ReadBytes, counter); list.Add(Expression.Assign(buffer, ReadBytesCaller)); var ms = Expression.Variable(typeof(MemoryStream), "ms"); var newMs = Expression.New(typeof(MemoryStream).GetConstructor(new Type[] { typeof(byte[]) }), buffer); //((IIndexerPersist<string>)persist[0]).Load(new BinaryReader(ms), (idx, value) => { values(idx, new Data<string>(value)); }, count); var castPersist = Expression.Convert(Expression.Constant(Persists[0]), Persists[0].GetType()); var loadMethod = Persists[0].GetType().GetMethod("Load"); var binaryReader = Expression.New(typeof(BinaryReader).GetConstructor(new Type[] { typeof(MemoryStream) }), ms); var idx = Expression.Variable(typeof(int), "idx"); var value = Expression.Variable(DataType.PrimitiveType, "value"); var newData = Expression.New(DataTypeUtils.GetDataType(DataType).GetConstructor(new Type[] { DataType.PrimitiveType }), value); var internalCall = Expression.Call(values, values.Type.GetMethod("Invoke"), idx, newData); var func = Expression.Lambda(internalCall, idx, value); var loadCall = Expression.Call(castPersist, loadMethod, binaryReader, func, count); //byte[] buffer = reader.ReadBytes((int)CountCompression.Deserialize(reader)); //using (MemoryStream ms = new MemoryStream(buffer)) //((IIndexerPersist<string>)persist[0]).Load(new BinaryReader(ms), (idx, value) => { values(idx, new Data<string>(value)); }, count); var usingBody = ms.Using(newMs, loadCall); list.Add(usingBody); var lambda = Expression.Lambda <Action <BinaryReader, Action <int, IData>, int> >(Expression.Block(new ParameterExpression[] { buffer }, list), new ParameterExpression[] { reader, values, count }); return(lambda); }
private Expression <Func <IData, IData, int> > CreateCompareMethod() { var x = Expression.Parameter(typeof(IData), "x"); var y = Expression.Parameter(typeof(IData), "y"); var idataType = DataTypeUtils.GetDataType(DataType); var data1 = Expression.Variable(idataType, "data1"); var data2 = Expression.Variable(idataType, "data2"); var cmp = Expression.Variable(typeof(int), "cmp"); List <Expression> list = new List <Expression>(); list.Add(Expression.Assign(data1, Expression.Convert(x, idataType))); list.Add(Expression.Assign(data2, Expression.Convert(y, idataType))); var exitPoint = Expression.Label(typeof(int)); if (DataType.IsPrimitive) { foreach (var command in GetCompareCommands(data1, data2, cmp, exitPoint, DataType, 0, CompareOptions[0], true)) { list.Add(command); } } else { for (int i = 0; i < DataType.TypesCount; i++) { foreach (var command in GetCompareCommands(data1, data2, cmp, exitPoint, DataType[i], i, CompareOptions[i], i == DataType.TypesCount - 1)) { list.Add(command); } } } list.Add(Expression.Label(exitPoint, Expression.Constant(0))); var body = Expression.Block(typeof(int), (new ParameterExpression[] { data1, data2, cmp }), list); var lambda = Expression.Lambda <Func <IData, IData, int> >(body, x, y); return(lambda); }
public DataPersist(DataType dataType) { bool supported = dataType.IsPrimitive || (dataType.IsSlotes && dataType.AreAllTypesPrimitive); if (!supported) { throw new NotSupportedException(dataType.ToString()); } DataType = dataType; Type = DataTypeUtils.GetDataType(dataType); //prepare Write LambdaWrite = CreateWriteMethod(); write = LambdaWrite.Compile(); //prepare Read LambdaRead = CreateReadMethod(); read = LambdaRead.Compile(); }
public DataToObjectsTransformer(DataType dataType) { bool supported = dataType.IsPrimitive || (dataType.IsSlotes && dataType.AreAllTypesPrimitive); if (!supported) { throw new NotSupportedException(dataType.ToString()); } DataType = dataType; Type = DataTypeUtils.GetDataType(DataType); //prepare toIData LambdaToIData = CreateToIDataMethod(); toIData = LambdaToIData.Compile(); //prepare fromIData LambdaFromIData = CreateFromIDataMethod(); fromIData = LambdaFromIData.Compile(); }
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); }
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); }
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); }
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); }