コード例 #1
0
    private LambdaExpression CreateExpression(Expression <Func <Entity, bool> > condition, Type type)
    {
        var lambda = (LambdaExpression)condition;

        if (!typeof(Entity).IsAssignableFrom(type))
        {
            return(null);
        }
        var newParams = new[] { Expression.Parameter(type, "entity") };
        var paramMap  = lambda.Parameters.Select((original, i) => new { original, replacement = newParams[i] }).ToDictionary(p => p.original, p => p.replacement);
        var fixedBody = ParameterRebinder.ReplaceParameters(paramMap, lambda.Body);

        lambda = Expression.Lambda(fixedBody, newParams);
        return(lambda);
    }
コード例 #2
0
        public static Expression <T> Compose <T>(this Expression <T> first, Expression <T> second,
                                                 Func <Expression, Expression, Expression> merge)
        {
            // build parameter map (from parameters of second to parameters of first)
            var map = first.Parameters
                      .Select((f, i) => new { f, s = second.Parameters[i] })
                      .ToDictionary(p => p.s, p => p.f);

            // replace parameters in the second lambda expression with parameters from
            // the first
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // apply composition of lambda expression bodies to parameters from
            // the first expression
            return(Expression.Lambda <T>(merge(first.Body, secondBody), first.Parameters));
        }
コード例 #3
0
        /// <summary>
        /// Combines the first expression with the second using the specified merge function.
        /// </summary>
        static Expression <T> Compose <T>(
            this Expression <T> first, Expression <T> second, Func <Expression,
                                                                    Expression, Expression> merge)
        {
            // zip parameters (map from parameters of second to parameters of first)
            var map = first.Parameters
                      .Select((f, i) => new { f, s = second.Parameters[i] })
                      .ToDictionary(p => p.s, p => p.f);

            // replace parameters in the second lambda expression
            // with the parameters in the first
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // create a merged lambda expression with parameters from the first expression
            return(Expression.Lambda <T>(merge(first.Body, secondBody), first.Parameters));
        }
コード例 #4
0
        private static Expression <T> Compose <T>(
            this Expression <T> first,
            Expression <T> second,
            Func <Expression, Expression, Expression> merge)
        {
            var map = first.Parameters
                      .Select((f, i) =>
                              new
            {
                f,
                s = second.Parameters[i]
            })
                      .ToDictionary(p => p.s, p => p.f);

            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            return(Expression.Lambda <T>(merge(first.Body, secondBody), first.Parameters));
        }
コード例 #5
0
        public static Expression <Func <T, bool> > CreateIsAfterFilter <T>(
            Expression <Func <T, DateTimeOffset> > getTimestampFromItem,
            DateTimeOffset timestampExclusive)
        {
            // Translate Expression<Func<T, DateTime>> to Expression<Func<T, bool>>
            // aka Translate 'get date for item' to 'is newer than last cache date'
            var inputParameter = Expression.Parameter(typeof(T), "a");

            //Expression getTimestampExpression;
            //if (getTimestampFromItem.Body is MemberExpression)
            //{
            //    //getTimestampExpression = Expression.Lambda<Func<DateTimeOffset>>(getTimestampFromItem, inputParameter);
            //    //getTimestampExpression = Expression.Invoke(getTimestampFromItem, inputParameter);
            //    getTimestampExpression = Expression.Lambda(getTimestampFromItem.Body, inputParameter);
            //}
            //else
            //{
            //    getTimestampExpression = Expression.Invoke(getTimestampFromItem, inputParameter);
            //}

            ////var nullValue = Expression.Constant(null, typeof(DateTime?));
            ////var isNotNull = Expression.NotEqual(getTimestampExpression, nullValue);

            //var dateValue = Expression.Constant(timestampExclusive, typeof(DateTimeOffset));
            //var isAfterDate = Expression.GreaterThan(getTimestampExpression, dateValue);

            ////var and = Expression.And(isNotNull, isAfterDate);

            //Expression<Func<T, bool>> isAfterDateLambda = Expression.Lambda<Func<T, bool>>(isAfterDate, inputParameter);

            var isAfterDateLambda = Expression.Lambda <Func <T, bool> >(
                Expression.GreaterThan(
                    ParameterRebinder.ReplaceParameters(
                        getTimestampFromItem.Parameters.ToDictionary(p => p, p => inputParameter),
                        getTimestampFromItem.Body),
                    Expression.Constant(timestampExclusive, typeof(DateTimeOffset))),
                inputParameter);

            ;

            Expression isAfterFilter = isAfterDateLambda.Body;

            return(isAfterDateLambda);
        }
コード例 #6
0
    /// <summary>
    /// Adapt a QueryConditional to the member we're currently visiting.
    /// </summary>
    /// <param name="condition">The condition to adapt</param>
    /// <param name="type">The type of the current member (=Navigation property)</param>
    /// <returns>The adapted QueryConditional</returns>
    private LambdaExpression CreateExpression(Expression <Func <ITranslation, bool> > condition, Type type)
    {
        var lambda        = (LambdaExpression)condition;
        var conditionType = condition.GetType().GetGenericArguments().First().GetGenericArguments().First();

        // Only continue when the condition is applicable to the Type of the member
        if (conditionType == null)
        {
            return(null);
        }
        if (!conditionType.IsAssignableFrom(type))
        {
            return(null);
        }
        var newParams = new[] { Expression.Parameter(type, "bo") };
        var paramMap  = lambda.Parameters.Select((original, i) => new { original, replacement = newParams[i] }).ToDictionary(p => p.original, p => p.replacement);
        var fixedBody = ParameterRebinder.ReplaceParameters(paramMap, lambda.Body);

        lambda = Expression.Lambda(fixedBody, newParams);
        return(lambda);
    }
コード例 #7
0
        private static Expression <T> Compose <T>(Expression <T> first, Expression <T> second, Func <Expression, Expression, Expression> merge)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }

            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }

            // build parameter map (from parameters of second to parameters of first)
            var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);


            // replace parameters in the second lambda expression with parameters from the first
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // apply composition of lambda expression bodies to parameters from the first expression
            return(Expression.Lambda <T>(merge(first.Body, secondBody), first.Parameters));
        }
コード例 #8
0
        public static LambdaExpression Compose(this LambdaExpression first, LambdaExpression second, Func <Expression, Expression, Expression> merge)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            if (merge == null)
            {
                throw new ArgumentNullException("merge");
            }

            // build parameter map (from parameters of second to parameters of first)
            var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            // replace parameters in the second lambda expression with parameters from the first
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // apply composition of lambda expression bodies to parameters from the first expression
            return(Expression.Lambda(first.Type, merge(first.Body, secondBody), first.Parameters));
        }
コード例 #9
0
        /// <summary>
        /// 以特定的条件运行组合两个Expression表达式
        /// </summary>
        /// <typeparam name="T">表达式的主实体类型</typeparam>
        /// <param name="first">第一个Expression表达式</param>
        /// <param name="second">要组合的Expression表达式</param>
        /// <param name="merge">组合条件运算方式</param>
        /// <returns>组合后的表达式</returns>
        public static Expression <T> Compose <T>(this Expression <T> first, Expression <T> second,
                                                 Func <Expression, Expression, Expression> merge)
        {
            if (!new NotNull().IsValid(first))
            {
                throw new ArgumentNullException(nameof(first));
            }

            if (!new NotNull().IsValid(second))
            {
                throw new ArgumentNullException(nameof(second));
            }

            if (!new NotNull().IsValid(second))
            {
                throw new ArgumentNullException(nameof(second));
            }

            var map =
                first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            return(Expression.Lambda <T>(merge(first.Body, secondBody), first.Parameters));
        }
コード例 #10
0
        //public class UserClass2
        //{
        //    public Bar b;
        //    public Foo f;
        //}
        //public class UserClass3
        //{
        //    public Bar b;
        //    public Foo f;
        //    public Qux q;
        //}
        //public static IQueryable<JoinClass<T1, T2, T3>> UserJoin<T, T1, T2, T3>(
        //    MyContext db,
        //    Expression<Func<JoinClass<T1, T2, T3>, bool>> JoinCond
        //)
        //    where T : class
        //    where T3 : class
        //    where T2 : class
        //    where T1 : class
        //{
        //    var jfb = Expression.Parameter(typeof(T), "jfb");

        //    FieldInfo[] ItemsT = typeof(T).GetFields();
        //    MemberExpression[] pars = ItemsT.Select(item => Expression.Field(jfb, item)).ToArray();


        //    var old_expr = JoinCond;
        //    var map = old_expr.Parameters.ToDictionary(p => p, p => jfb);
        //    var reboundBody = ParameterRebinder.ReplaceParameters(map, old_expr.Body);
        //    var newCond = Expression.Lambda(reboundBody, jfb).Body;

        //    var WhereExpr = Expression.Lambda<Func<JoinClass<T1, T2, T3>, bool>>(newCond, jfb);

        //    Type[] types = ItemsT.Select(item => item.FieldType).ToArray();

        //    MethodInfo method = typeof(LinqToDB.Data.DataConnection).GetMethods()[32];
        //    MethodInfo[] generic = types.Select(t => method.MakeGenericMethod(t) ).ToArray();
        //    object[] tables = generic.Select(g => g.Invoke(db, null)).ToArray();


        //    var qx = ((IQueryable<T1>)tables[0])
        //            .SelectMany(
        //            b => db.GetTable<T2>(), (b, f) => new JoinClass<T1, T2>() { t1 = b, t2 = f })
        //            .SelectMany(
        //            q => db.GetTable<T3>()
        //                , (j, q) => new JoinClass<T1, T2, T3>() { t1 = j.t1, t2 = j.t2, t3 = q });


        //    return qx.Where(WhereExpr);

        //}



        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");



            Console.WriteLine("by Id int");

            using (var db = new MyContext()) {
                var queryJoinById = MultiJoin <Bar, Foo>(db, j => j.t1.id == j.t2.id);
                //Test.NewJoin<Bar, Foo, int, Tuple<Bar,Foo>>(q => q.id, b => b.id, (f, b) => new Tuple<Bar,Foo>(b,f));
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));
                ConsoleOut(queryJoinById);
                Console.WriteLine("-------------");

                Console.WriteLine("by Col string");
                var queryJoinByCol = MultiJoin <Bar, Foo>(db, j => j.t2.ColFoo.StartsWith(j.t1.ColBar));
                //Test.NewJoin<Bar, Foo, string, Tuple<Bar,Foo>>(q => q.ColFoo, b => b.ColBar, (f, b) => new Tuple<Bar,Foo>(b,f));
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));
                ConsoleOut(queryJoinByCol);
                Console.WriteLine("-------------");


                Console.WriteLine("by Col string AND Id int");

                var w = MultiJoin <Bar, Foo>(db,
                                             j => j.t2.ColFoo.StartsWith(j.t1.ColBar) && j.t1.id == j.t2.id
                                             );
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));
                ConsoleOut(w); //.Select(j => new Tuple<Bar,Foo>(j.t1,j.t2))

                var test = MultiJoin <Bar, Qux>(db,
                                                j => j.t1.id == j.t2.id && !j.t2.Success
                                                );

                Console.WriteLine(String.Join(",",
                                              test.Select(t => t.t1.Name)
                                              )
                                  );
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));

                var complex = MultiJoin <Bar, Foo, Qux, Baz>(db,
                                                             j => (j.t2.id == 0 || j.t2.ColFoo.StartsWith(j.t1.ColBar)) && j.t1.id == j.t3.id &&
                                                             !j.t3.Success && j.t4.id == j.t1.id
                                                             );
                Console.WriteLine(String.Join(",",
                                              complex.Select(t => t.t1.Name + "@" + t.t2.FromDate.ToShortDateString() + "*" + t.t4.Sex)
                                              )
                                  );
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));


                var left = db.GetTable <Bar>()
                           .SelectMany(
                    b => db.GetTable <Baz>().Where(x => x.id == b.id).DefaultIfEmpty()
                    , (b, f) => new JoinClass <Bar, Baz>()
                {
                    t1 = b, t2 = f
                });

                Console.WriteLine(String.Join(",",
                                              left.Select(t => t.t1.Name + "*" + (t.t2 == null ? "-" : t.t2.Sex.Equals('M')?"M":"F"))
                                              )
                                  );
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));

                var linqjoin = db.GetTable <Bar>().Join(db.GetTable <Baz>(), x => x.id, y => y.id,
                                                        (x, y) => new  { x, y }).ToArray();

                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));

                var qleft = from b in db.GetTable <Bar>()
                            join z in db.GetTable <Baz>() on b.id equals z.id into g
                            from s in g.DefaultIfEmpty()
                            select new { b, s };
                qleft.ToArray();
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));

                var nonqleft = db.GetTable <Bar>().GroupJoin(db.GetTable <Baz>(), x => x.id, y => y.id,
                                                             (x, y) => new { x, y })
                               .SelectMany(t => t.y.DefaultIfEmpty()
                                           , (o, i) => new { Outer = o.x, Inner = i })
                               .ToArray();
                Console.WriteLine(String.Format("Last Query: {0}", db.LastQuery));
                Console.WriteLine(String.Join(",",
                                              nonqleft.Select(t => t.Outer.Name + "*" + (t.Inner == null ? "-" : t.Inner.Sex.Equals('M') ? "M" : "F"))
                                              )
                                  );

                //var super = UserJoin< UserClass3, Bar, Foo, Qux>(db,
                //    j => j.f.ColFoo.StartsWith(j.b.ColBar) && j.f.id == j.q.id && j.q.Success
                //    );
            }



            #region SO try to generalize the Equal Expr into LambdaExpr in the generic JoinCond
            //I have this expression
            Expression <Func <Bar, bool> > old_expr = x => x.Name == x.ColBar;
            //I want to change parameter from x to y
            //I already have the y parameter in the code, let's say it is the followinf
            ParameterExpression py = Expression.Parameter(typeof(Bar), "y");
            //this is what I have tried, but it is *not* complete neither generic
            Expression expr_to_do;
            if (old_expr.Body.NodeType.Equals(ExpressionType.Convert))
            {
                UnaryExpression convEx = old_expr.Body as UnaryExpression;
                expr_to_do = convEx.Operand;
            }
            else
            {
                expr_to_do = old_expr.Body;
            }
            //TODO convert the BinarayExpression eqEx, etc... etc...

            if (expr_to_do.NodeType.Equals(ExpressionType.Equal))
            {
                // have I to manage each Expr Type case??
                var eqExpr = expr_to_do as BinaryExpression;
                var left   = eqExpr.Left as MemberExpression;
                //...
                //var new_left = Expression.Property(...,py)
            }
            var newLambda = Expression.Lambda(expr_to_do, new ParameterExpression[1] {
                py
            });

            var map         = old_expr.Parameters.ToDictionary(p => p, p => py);
            var reboundBody = ParameterRebinder.ReplaceParameters(map, old_expr.Body);
            var lambda      = Expression.Lambda <Func <Bar, bool> >(reboundBody, py);

            //newLambda = Expression.Lambda(Expression.Call(
            //	old_expr.Compile().Method, new Expression[] {Expression.Constant(new Bar()),Expression.Constant(new Bar())})
            //                              ,new ParameterExpression[1]{py});

            //Again, what I want to get is the following where y *is* the parameter defined *above*
            Expression <Func <Bar, bool> > new_expr = y => y.Name == y.ColBar;
            //The code/method I'm looking for - if it does exist a method to do that - must be generic enough not specific to this single expression
            #endregion

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }