예제 #1
0
        private Action <TTarget, TSrc> CreateExpression(IEnumerable <string> fields)
        {
            var t1param = EE.Param <TTarget>("left");
            var t2param = EE.Param <TSrc>("right");

            var assignList = fields.Select(f =>
            {
                var propA = typeof(TTarget).GetProperty(f);
                var propB = typeof(TSrc).GetProperty(f);
                if (propA.PropertyType == propB.PropertyType)
                {
                    return(Expression.Assign(t1param.Dot(f), t2param.Dot(f)));
                }
                else if (propA.PropertyType == typeof(int) && propB.PropertyType.IsEnum ||
                         propB.PropertyType == typeof(int) && propA.PropertyType.IsEnum)
                {
                    return(Expression.Assign(t1param.Dot(f), Expression.Convert(t2param.Dot(f), propA.PropertyType)));
                }
                else if (Nullable.GetUnderlyingType(propB.PropertyType) == propA.PropertyType ||
                         Nullable.GetUnderlyingType(propA.PropertyType) == propB.PropertyType)
                {
                    return(Expression.Assign(t1param.Dot(f), Expression.Convert(t2param.Dot(f), propA.PropertyType)));
                }

                throw new InvalidOperationException($"Invalid operation, cannot copy {propB} to {propA}.");
            });
            //var resultArr = Expression.NewArrayInit(typeof(bool), cmplist);
            var block = Expression.Block(assignList);
            var l     = Expression.Lambda <Action <TTarget, TSrc> >(block, t1param, t2param);

            return(l.Compile());
        }
예제 #2
0
        private Func <T1, TVal[]> CreateExpression(IEnumerable <string> fields)
        {
            var t1param = EE.Param <T1>("obj");
            var elist   = fields.Select(f => t1param.Dot(f)).Cast <Expression>();

            if (typeof(TVal) == typeof(object))
            {
                elist = elist.Select(e => EE.Box(e));
            }
            var resultArr = Expression.NewArrayInit(typeof(TVal), elist);
            var l         = Expression.Lambda <Func <T1, TVal[]> >(resultArr, t1param);

            return(l.Compile());
        }
예제 #3
0
        private Func <T1, T2, DifferReturnValueType[]> CreateExpression(IEnumerable <string> fields)
        {
            var t1param     = EE.Param <T1>("left");
            var t2param     = EE.Param <T2>("right");
            var NULL        = EE.Val <DifferReturnValueType>(null);
            var TupleCreate = EE.Method(() => Tuple.Create <string, object>("", null));
            var cmplist2    = fields.Select(f =>
                                            Expression.Condition(t1param.Dot(f).IsEq(t2param.Dot(f)),
                                                                 NULL,
                                                                 Expression.Call(TupleCreate, EE.Val(f), EE.Box(t2param.Dot(f)))));
            var resultArr = Expression.NewArrayInit(typeof(DifferReturnValueType), cmplist2);

            var l = Expression.Lambda <Func <T1, T2, DifferReturnValueType[]> >(resultArr, t1param, t2param);

            return(l.Compile());
        }
예제 #4
0
        private Action <TTarget, TSrc> CreateExpression(IEnumerable <string> fields)
        {
            var targetParam = EE.Param <TTarget>("left");
            var sourceParam = EE.Param <TSrc>("right");

            IEnumerable <Expression> assignList = fields.Select(f =>
            {
                var propTarget = typeof(TTarget).GetProperty(f);
                var propSource = typeof(TSrc).GetProperty(f);
                if (propTarget.PropertyType == propSource.PropertyType)
                {
                    return(Expression.Assign(targetParam.Dot(f), sourceParam.Dot(f)) as Expression);
                }
                else if (propTarget.PropertyType == typeof(int) && propSource.PropertyType.IsEnum ||
                         propSource.PropertyType == typeof(int) && propTarget.PropertyType.IsEnum)
                {
                    return(Expression.Assign(targetParam.Dot(f), Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType)));
                }
                // assigning nullable to non-nullable creates prop = default(T)
                else if (Nullable.GetUnderlyingType(propSource.PropertyType) == propTarget.PropertyType)
                {
                    var iffed = Expression.IfThenElse(sourceParam.Dot(f).NotNull(),
                                                      Expression.Assign(targetParam.Dot(f),
                                                                        Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType)),
                                                      Expression.Assign(targetParam.Dot(f), Expression.Default(propTarget.PropertyType)));
                    return(iffed);
                }
                // target is nullable, source is not - nothing special, it will never get null
                else if (Nullable.GetUnderlyingType(propTarget.PropertyType) == propSource.PropertyType)
                {
                    return(Expression.Assign(targetParam.Dot(f), Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType)));
                }

                throw new InvalidOperationException($"Invalid operation, cannot copy {propSource} to {propTarget}.");
            });
            //var resultArr = Expression.NewArrayInit(typeof(bool), cmplist);
            var block = Expression.Block(assignList);
            var l     = Expression.Lambda <Action <TTarget, TSrc> >(block, targetParam, sourceParam);

            return(l.Compile());
        }
예제 #5
0
        private Func <T1, int> CreateExpression(PropertyInfo[] fields, FieldHasherOptions options)
        {
            /*
             * $hash = 17;
             * $hash += $hash * 23 + .Call ($obj.a).GetHashCode();
             * $hash += $hash * 23 + .Call ($obj.b).GetHashCode();
             * .If ($obj.s != null) {
             *  $hash += $hash * 23 + .Call (.Call ($obj.s).Trim()).GetHashCode()
             * } .Else {
             *  $hash *= 23
             * };
             * $hash += $hash * 23 + .Call ($obj.date).GetHashCode();
             * $hash += $hash * 23 + .Call ($obj.mynullable).GetHashCode();
             * $hash
             */
            const int prim       = 17;
            const int prim2      = 23;
            var       t1param    = EE.Param <T1>("obj");
            var       resultHash = EE.Param <int>("hash");
            var       ass        = Expression.Assign(resultHash, Expression.Constant(prim));
            var       block      = new List <Expression>();

            block.Add(ass);
            var returnLabel = Expression.Label(typeof(int));

            var whenNull = options.ZeroIfNulls ? Expression.Return(returnLabel, Expression.Constant(0))
                : resultHash.MulAssign(prim2);

            block.AddRange(fields.Select(pi =>
            {
                var dotted   = t1param.Dot(pi.Name);
                var propType = pi.PropertyType;

                var addAssignHashCode = Expression.AddAssign(resultHash,
                                                             resultHash.Mul(prim2).Add(dotted.Call("GetHashCode")));

                // nullable
                if (options.ZeroIfNulls && Nullable.GetUnderlyingType(propType) != null)
                {
                    return(Expression.IfThenElse(
                               dotted.NotNull(),
                               addAssignHashCode,
                               whenNull));
                }

                // value type but not nullabl
                if (propType.IsValueType)
                {
                    return((Expression)addAssignHashCode);
                }


                // normalized string
                var normalized = propType == typeof(string) && options.StringNormalizer != null
                    ? options.StringNormalizer(dotted)
                    : dotted;

                var iffed = Expression.IfThenElse(dotted.NotNull(),
                                                  Expression.AddAssign(resultHash,
                                                                       resultHash.Mul(prim2).Add(normalized.Call("GetHashCode"))),
                                                  whenNull);

                return(iffed);
            }));

            block.Add(Expression.Label(returnLabel, resultHash));
            var eblock = Expression.Block(new [] { resultHash }, block);
            var l      = Expression.Lambda <Func <T1, int> >(eblock, t1param);

            return(l.Compile());
        }