示例#1
0
        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();
        }
示例#2
0
        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());
        }
示例#3
0
        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);
        }
示例#4
0
        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();
        }
示例#5
0
        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);
        }
示例#6
0
        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));
            }
        }
示例#7
0
        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));
            }
        }
示例#8
0
        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);
        }
示例#9
0
        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());
        }
示例#10
0
        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());
        }
示例#11
0
        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));
        }
示例#12
0
        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));
        }
示例#13
0
        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);
        }
示例#14
0
        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));
        }
示例#15
0
        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());
        }
示例#16
0
        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);
        }
示例#17
0
        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));
        }
示例#18
0
        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());
        }
示例#19
0
 private IEnumerable <MemberInfo> GetPublicMembers(Type type)
 {
     return(DataTypeUtils.GetPublicMembers(type, MembersOrder));
 }