Beispiel #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();
        }
Beispiel #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());
        }
Beispiel #3
0
        public ValueToObjects(Func <Type, MemberInfo, int> membersOrder = null)
        {
            if (!DataType.IsPrimitiveType(typeof(T)) && !typeof(T).HasDefaultConstructor())
            {
                throw new NotSupportedException("No default constructor.");
            }

            bool isSupported = DataTypeUtils.IsAllPrimitive(typeof(T));

            if (!isSupported)
            {
                throw new NotSupportedException("Not all types are primitive.");
            }

            Type         = typeof(T);
            MembersOrder = membersOrder;

            LambdaFromObjects = CreateFromObjectsMethod();
            fromObjects       = LambdaFromObjects.Compile();

            LambdaToObjects = CreateToObjectsMethod();
            toObjects       = LambdaToObjects.Compile();
        }
        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));
            }
        }
Beispiel #5
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());
        }
Beispiel #6
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());
        }
Beispiel #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));
            }
        }
Beispiel #8
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.AllButTop && !isTop);

            if (itemType == typeof(Guid))
            {
                return(Expression.New(itemType.GetConstructor(new Type[] { typeof(byte[]) }), GetReadCommand(reader, typeof(byte[]), canBeNull)));
            }

            if (itemType.IsEnum)
            {
                return(Expression.Convert(GetReadCommand(reader, itemType.GetEnumUnderlyingType(), canBeNull), itemType));
            }

            if (DataType.IsPrimitiveType(itemType))
            {
                return(GetReadCommand(reader, itemType, canBeNull));
            }

            if (itemType.IsKeyValuePair())
            {
                var newKeyValuePair = 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 (canBeNull)
                {
                    return(Expression.Block(Expression.Call(reader, typeof(BinaryReader).GetMethod("ReadBoolean")), newKeyValuePair));
                }

                return(newKeyValuePair);
            }

            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())
            {
                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 (itemType.IsStruct())
                {
                    if (canBeNull)
                    {
                        list.Insert(0, Expression.Call(reader, typeof(BinaryReader).GetMethod("ReadBoolean")));
                    }

                    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());
        }
Beispiel #9
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.AllButTop && !isTop);

            if (type == typeof(Guid))
            {
                return(GetWriteCommand(writer, Expression.Call(item, type.GetMethod("ToByteArray")), canBeNull));
            }

            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())
            {
                if (!canBeNull)
                {
                    return(Expression.Block(
                               BuildWrite(Expression.PropertyOrField(item, "Key"), writer, membersOrder, allowNull, false),
                               BuildWrite(Expression.PropertyOrField(item, "Value"), writer, membersOrder, allowNull, false)
                               ));
                }

                return(Expression.Block(
                           Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(true)),
                           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 => BuildWrite(type.IsArray ? Expression.ArrayAccess(item, i) : item.This(i), writer, membersOrder, allowNull, false), 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 => BuildWrite(type.IsArray ? Expression.ArrayAccess(item, i) : item.This(i), writer, membersOrder, allowNull, false), 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),
                                                BuildWrite(Expression.PropertyOrField(kv, "Key"), writer, membersOrder, allowNull, false),
                                                BuildWrite(Expression.PropertyOrField(kv, "Value"), writer, membersOrder, allowNull, false)
                                                );
                    }, 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),
                                            BuildWrite(Expression.PropertyOrField(kv, "Key"), writer, membersOrder, allowNull, false),
                                            BuildWrite(Expression.PropertyOrField(kv, "Value"), writer, membersOrder, allowNull, false)
                                            );
                }, Expression.Label())),
                                             Expression.Call(writer, typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(bool) }), Expression.Constant(false))
                                             ));
            }

            if (type.IsNullable())
            {
                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)
                {
                    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());
        }
Beispiel #10
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));
        }
Beispiel #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));
        }
Beispiel #12
0
        internal 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));
        }