Esempio n. 1
0
        public void AnonymousTypeTupletizer_TransparentIdentifiers()
        {
            Expression <Func <IEnumerable <int>, IEnumerable <string>, IEnumerable <bool> > > f = (xs, ys) => from x in xs
                                                                                                  from y in ys
                                                                                                  let l                 = y.Length
                                                                                                                  let k = x * l
                                                                                                                          where l > 0
                                                                                                                          where k != 1
                                                                                                                          let b = x + l < 42
                                                                                                                                  select !b;

            //Expression<Func<IEnumerable<int>, IEnumerable<string>, IEnumerable<bool>>> g = (xs, ys) => xs
            //                                                                                           .SelectMany(x => ys, (x, y) => new { x = x, y = y })
            //                                                                                           .Select(t => new { t, l = t.y.Length })
            //                                                                                           .Select(t => new { t, k = t.t.x * t.l })
            //                                                                                           .Where(t => t.t.l > 0)
            //                                                                                           .Where(t => t.k != 1)
            //                                                                                           .Select(t => new { t, b = t.t.t.x + t.t.l < 42 })
            //                                                                                           .Select(t => !t.b);

            Expression <Func <IEnumerable <int>, IEnumerable <string>, IEnumerable <bool> > > g = (xs, ys) => xs
                                                                                                  .SelectMany(x => ys, (x, y) => new Tuple <int, string>(x, y))
                                                                                                  .Select(t => new Tuple <Tuple <int, string>, int>(t, t.Item2.Length))
                                                                                                  .Select(t => new Tuple <Tuple <Tuple <int, string>, int>, int>(t, t.Item1.Item1 * t.Item2))
                                                                                                  .Where(t => t.Item1.Item2 > 0)
                                                                                                  .Where(t => t.Item2 != 1)
                                                                                                  .Select(t => new Tuple <Tuple <Tuple <Tuple <int, string>, int>, int>, bool>(t, t.Item1.Item1.Item1 + t.Item1.Item2 < 42))
                                                                                                  .Select(t => !t.Item2);

            var te = AnonymousTypeTupletizer.Tupletize(f, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(g, te));
        }
Esempio n. 2
0
        public void ConstantHoister_ManOrBoy()
        {
#pragma warning disable IDE0079 // The following supression is flagged as unnecessary on .NET Framework (but is required for other targets)
#pragma warning disable CA1845  // Use span-based 'string.Concat' and 'AsSpan' instead of 'Substring'
            var e = (Expression <Func <IEnumerable <int>, IEnumerable <string> > >)(xs => from x in xs let y = x + 1 where y > 0 let s = x.ToString() where !s.EndsWith("Foo") select s.Substring(0, 1) + "Foo");
#pragma warning restore CA1847
#pragma warning restore IDE0079
            var c = ConstantHoister.Hoist(e, useDefaultForNull: false);

            Assert.AreEqual(3, c.Environment.Count);
            Assert.IsTrue(c.Environment.Values.Contains(0));
            Assert.IsTrue(c.Environment.Values.Contains(1));
            Assert.IsTrue(c.Environment.Values.Contains("Foo"));

            var i = (Expression)c.ToInvocation();

            Assert.AreEqual("((Func<int, int, string, Func<IEnumerable<int>, IEnumerable<string>>>)((int @p0, int @p1, string @p2) => (IEnumerable<int> xs) => xs.Select((int x) => new { x, y = x + @p0 }).Where(t => t.y > @p1).Select(t => new { t, s = t.x.ToString() }).Where(t => !t.s.EndsWith(@p2)).Select(t => t.s.Substring(@p1, @p0) + @p2)))(1, 0, \"Foo\")", i.ToCSharpString());
            Assert.AreEqual("int @p0 = 1;\r\nint @p1 = 0;\r\nstring @p2 = \"Foo\";\r\nreturn (IEnumerable<int> xs) => xs.Select((int x) => new { x, y = x + @p0 }).Where(t => t.y > @p1).Select(t => new { t, s = t.x.ToString() }).Where(t => !t.s.EndsWith(@p2)).Select(t => t.s.Substring(@p1, @p0) + @p2);\r\n", c.ToCSharpString());

            var t = c.ToString();
            var u = Regex.Replace(t, @"\<\>f__AnonymousType[\da-fA-F]*", "anon");
            var v = Regex.Replace(u, @"\<\>h__TransparentIdentifier[\da-fA-F]*", "tran");

            Assert.AreEqual("(xs => xs.Select(x => new anon`2(x = x, y = (x + @p0))).Where(tran => (tran.y > @p1)).Select(tran => new anon`2(tran = tran, s = tran.x.ToString())).Where(tran => Not(tran.s.EndsWith(@p2))).Select(tran => (tran.s.Substring(@p1, @p0) + @p2)))[|@p0 : System.Int32 = 1, @p1 : System.Int32 = 0, @p2 : System.String = \"Foo\"|]", v);

            i = AnonymousTypeTupletizer.Tupletize(i, Expression.Constant(value: null));
            i = CompilerGeneratedNameEliminator.Prettify(i);

            var f = i.Evaluate <Func <IEnumerable <int>, IEnumerable <string> > >();
            var g = f(new[] { 123, 234, 987, 876 });
            Assert.IsTrue(new[] { "1Foo", "2Foo", "9Foo", "8Foo" }.SequenceEqual(g));

            Assert.AreEqual(@"Invoke((@p0, @p1, @p2) => xs => xs.Select(x => new Tuple`2(x, (x + @p0))).Where(t => (t.Item2 > @p1)).Select(t => new Tuple`2(t, t.Item1.ToString())).Where(t => Not(t.Item2.EndsWith(@p2))).Select(t => (t.Item2.Substring(@p1, @p0) + @p2)), 1, 0, ""Foo"")", i.ToString());
        }
Esempio n. 3
0
        public void AnonymousTypeTupletizer_RecursiveType()
        {
            var rtc = new RuntimeCompiler();

            var atb1 = rtc.GetNewAnonymousTypeBuilder();
            var atb2 = rtc.GetNewAnonymousTypeBuilder();

            rtc.DefineAnonymousType(atb1, new[]
            {
                new KeyValuePair <string, Type>("Qux", typeof(int)),
                new KeyValuePair <string, Type>("Bar", atb2),
            }, Array.Empty <string>());

            rtc.DefineAnonymousType(atb2, new[]
            {
                new KeyValuePair <string, Type>("Baz", typeof(int)),
                new KeyValuePair <string, Type>("Foo", atb1),
            }, Array.Empty <string>());

            var foo = atb1.CreateType();
            var bar = atb2.CreateType();

            var e = Expression.New(foo.GetConstructors().Single(), Expression.Constant(1), Expression.Constant(value: null, bar));

            Assert.ThrowsException <NotSupportedException>(() => AnonymousTypeTupletizer.Tupletize(e, Expression.Constant(value: null)));
        }
Esempio n. 4
0
        public void AnonymousTypeTupletizer_ArgumentChecking()
        {
            AssertEx.ThrowsException <ArgumentNullException>(() => AnonymousTypeTupletizer.Tupletize(expression: null, Expression.Constant(1)), ex => Assert.AreEqual("expression", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => AnonymousTypeTupletizer.Tupletize(Expression.Constant(1), unitValue: null), ex => Assert.AreEqual("unitValue", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => AnonymousTypeTupletizer.Tupletize(expression: null, Expression.Constant(1), excludeVisibleTypes: true), ex => Assert.AreEqual("expression", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => AnonymousTypeTupletizer.Tupletize(Expression.Constant(1), unitValue: null, excludeVisibleTypes: true), ex => Assert.AreEqual("unitValue", ex.ParamName));
        }
Esempio n. 5
0
        public void AnonymousTypeTupletizer_Constant_NotSupported()
        {
            var e = (NewExpression)((Expression <Func <object> >)(() => new { a = 42, b = new[] { new { c = 42 } } })).Body;

            var arg0 = e.Arguments[0];
            var arg1 = e.Arguments[1];

            var a = e.Update(new Expression[] { arg0, Expression.Constant(arg1.Evaluate <object>(), arg1.Type) });

            Assert.ThrowsException <InvalidOperationException>(() => _ = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null)));
        }
Esempio n. 6
0
        /// <summary>
        /// Normalizes the specified expression prior to submission to the service.
        /// </summary>
        /// <param name="expression">The expression to normalize.</param>
        /// <returns>The normalized expression.</returns>
        public override Expression Normalize(Expression expression)
        {
            // TODO: [IRP Core] Ordering of the rewrites (base/here; exposure of virtuals).

            // Runs a standard set of rewrites, causing callbacks to the Funcletize method below.
            var normalized = base.Normalize(expression);

            // Replaces compiler-generated anonymous types, e.g. for transparent identifiers, by tuples which don't need reconstruction in the service.
            var tupletized = AnonymousTypeTupletizer.Tupletize(normalized, Expression.Constant(null), excludeVisibleTypes: true);

            return(tupletized);
        }
Esempio n. 7
0
        public void AnonymousTypeTupletizer_Simple0()
        {
            Expression <Func <object> > f = () => new { };
            var a = f.Body;

            var b = Expression.Constant(value: null);
            var t = AnonymousTypeTupletizer.Tupletize(a, b);

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 8
0
        public void AnonymousTypeTupletizer_Constant_Simple2()
        {
            var x = new { a = 42, b = "bar" };

            var a = Expression.Constant(x);
            var b = Expression.Constant(new Tuple <int, string>(42, "bar"));

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 9
0
        public void AnonymousTypeTupletizer_Constant_Simple9()
        {
            var x = new { a = 42, b = "bar", c = 12.34, d = false, e = 'a', f = 49.95m, g = 0.1f, h = (byte)128, i = new TimeSpan(1, 2, 3) };

            var a = Expression.Constant(x);
            var b = Expression.Constant(new Tuple <int, string, double, bool, char, decimal, float, Tuple <byte, TimeSpan> >(42, "bar", 12.34, false, 'a', 49.95m, 0.1f, new Tuple <byte, TimeSpan>(128, new TimeSpan(1, 2, 3))));

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 10
0
        public void AnonymousTypeTupletizer_Constant_Simple0()
        {
            var x = new { };

            var a = Expression.Constant(x);
            var b = Expression.Constant("bar");

            var t = AnonymousTypeTupletizer.Tupletize(a, b);

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 11
0
        public void AnonymousTypeTupletizer_Constant_Null()
        {
            var x = new { a = 42 };

            var a = Expression.Constant(value: null, x.GetType());
            var b = Expression.Constant(value: null, typeof(Tuple <int>));

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 12
0
        public void AnonymousTypeTupletizer_Simple10()
        {
            Expression <Func <object> > f = () => new { a = 42, b = "bar", c = 3.14, d = false, e = 49.95m, f = DateTime.Now, g = new TimeSpan(1, 2, 3), h = Guid.NewGuid(), i = (byte)128, j = 12.34f };
            var a = f.Body;

            Expression <Func <object> > g = () => new Tuple <int, string, double, bool, decimal, DateTime, TimeSpan, Tuple <Guid, byte, float> >(42, "bar", 3.14, false, 49.95m, DateTime.Now, new TimeSpan(1, 2, 3), new Tuple <Guid, byte, float>(Guid.NewGuid(), 128, 12.34f));
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 13
0
        public void AnonymousTypeTupletizer_Nested3()
        {
            Expression <Func <int> > f = () => new { a = new { b = new { a = new { b = 42 } } } }.a.b.a.b;
            var a = f.Body;

            Expression <Func <int> > g = () => new Tuple <Tuple <Tuple <Tuple <int> > > >(new Tuple <Tuple <Tuple <int> > >(new Tuple <Tuple <int> >(new Tuple <int>(42)))).Item1.Item1.Item1.Item1;
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 14
0
        public void AnonymousTypeTupletizer_Nested1()
        {
            Expression <Func <object> > f = () => new { a = 42, b = new { c = "bar", d = false }, e = 12.34, f = new { g = 'a' } };
            var a = f.Body;

            Expression <Func <object> > g = () => new Tuple <int, Tuple <string, bool>, double, Tuple <char> >(42, new Tuple <string, bool>("bar", false), 12.34, new Tuple <char>('a'));
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
 public void AnonymousTypeTupletizer_NoChange()
 {
     foreach (var e in new Expression[]
     {
         Expression.Constant(1),
         (Expression <Func <int> >)(() => DateTime.Now.Year),
         (Expression <Func <TimeSpan> >)(() => new TimeSpan(1, 2, 3)),
         (Expression <Func <IEnumerable <int>, IEnumerable <string> > >)(xs => from x in xs where x % 2 == 0 select x.ToString())
     })
     {
         var t = AnonymousTypeTupletizer.Tupletize(e, Expression.Constant(value: null));
         Assert.AreSame(e, t);
     }
 }
Esempio n. 16
0
        public void AnonymousTypeTupletizer_Simple15_Accessor3()
        {
            Expression <Func <char> > f = () => new { a = 42, b = "bar", c = 3.14, d = false, e = 49.95m, f = DateTime.Now, g = new TimeSpan(1, 2, 3), h = Guid.NewGuid(), i = (byte)128, j = 12.34f, k = 24, l = true, m = "foo", n = (object)null, o = 'a' }.o;
            var a = f.Body;

            Expression <Func <char> > g = () => new Tuple <int, string, double, bool, decimal, DateTime, TimeSpan, Tuple <Guid, byte, float, int, bool, string, object, Tuple <char> > >(42, "bar", 3.14, false, 49.95m, DateTime.Now, new TimeSpan(1, 2, 3), new Tuple <Guid, byte, float, int, bool, string, object, Tuple <char> >(Guid.NewGuid(), 128, 12.34f, 24, true, "foo", null, new Tuple <char>('a'))).Rest.Rest.Item1;
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 17
0
        public void AnonymousTypeTupletizer_Simple8_Accessor2()
        {
            Expression <Func <Guid> > f = () => new { a = 42, b = "bar", c = 3.14, d = false, e = 49.95m, f = DateTime.Now, g = new TimeSpan(1, 2, 3), h = Guid.NewGuid() }.h;
            var a = f.Body;

            Expression <Func <Guid> > g = () => new Tuple <int, string, double, bool, decimal, DateTime, TimeSpan, Tuple <Guid> >(42, "bar", 3.14, false, 49.95m, DateTime.Now, new TimeSpan(1, 2, 3), new Tuple <Guid>(Guid.NewGuid())).Rest.Item1;
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 18
0
        public void AnonymousTypeTupletizer_Simple1_Accessor()
        {
            Expression <Func <int> > f = () => new { a = 42 }.a;
            var a = f.Body;

            Expression <Func <int> > g = () => new Tuple <int>(42).Item1;
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 19
0
        public void AnonymousTypeTupletizer_Simple2()
        {
            Expression <Func <object> > f = () => new { a = 42, b = "bar" };
            var a = f.Body;

            Expression <Func <object> > g = () => new Tuple <int, string>(42, "bar");
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));
        }
Esempio n. 20
0
        public void AnonymousTypeTupletizer_NoChange()
        {
            foreach (var e in new Expression[]
            {
                Expression.Constant(1),
#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <int> >)(() => DateTime.Now.Year),
                (Expression <Func <TimeSpan> >)(() => new TimeSpan(1, 2, 3)),
#pragma warning restore IDE0004
                (Expression <Func <IEnumerable <int>, IEnumerable <string> > >)(xs => from x in xs where x % 2 == 0 select x.ToString())
            })
            {
                var t = AnonymousTypeTupletizer.Tupletize(e, Expression.Constant(value: null));
                Assert.AreSame(e, t);
            }
        }
Esempio n. 21
0
        public void AnonymousTypeTupletizer_Simple2_ToString()
        {
            Expression <Func <string> > f = () => new { a = 42, b = "bar" }.ToString();
            var a = f.Body;

            Expression <Func <string> > g = () => new Tuple <int, string>(42, "bar").ToString();
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));

            Assert.AreEqual("{ a = 42, b = bar }", a.Evaluate <string>());
            Assert.AreEqual("(42, bar)", b.Evaluate <string>());
            Assert.AreEqual("(42, bar)", t.Evaluate <string>());
        }
Esempio n. 22
0
        public void AnonymousTypeTupletizer_Simple2_GetHashCode()
        {
            Expression <Func <bool> > f = () => new { a = 42, b = "bar" }.GetHashCode() == new { a = 42, b = "bar" }.GetHashCode();
            var a = f.Body;

            Expression <Func <bool> > g = () => new Tuple <int, string>(42, "bar").GetHashCode() == new Tuple <int, string>(42, "bar").GetHashCode();
            var b = g.Body;

            var t = AnonymousTypeTupletizer.Tupletize(a, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(b, t));

            Assert.IsTrue(a.Evaluate <bool>());
            Assert.IsTrue(b.Evaluate <bool>());
            Assert.IsTrue(t.Evaluate <bool>());
        }
Esempio n. 23
0
        public void AnonymousTypeTupletizer_ManOrBoy()
        {
            var expr = (from x in Enumerable.Empty <object>().AsQueryable()
                        group x by x into g
                        let a = g.OfType <bool>()
                                let b = g.OfType <string>()
                                        let z = Enumerable.Zip(a, b, (x, y) => new { x, y })
                                                from t in z
                                                select t.x ? t.y : "null")
                       .Expression;

            var res = AnonymousTypeTupletizer.Tupletize(expr, Expression.Constant(value: null));

            var csharp = CompilerGeneratedNameEliminator.Prettify(res).ToCSharpString();

            Assert.AreEqual(
                StripWhitespace(@"
                    __c0.GroupBy<object, object>((object x) => x)
                        .Select<IGrouping<object, object>, Tuple<IGrouping<object, object>, IEnumerable<bool>>>(
                            (IGrouping<object, object> g) =>
                                new Tuple<IGrouping<object, object>, IEnumerable<bool>>(
                                    g,
                                    g.OfType<bool>()))
                        .Select<Tuple<IGrouping<object, object>, IEnumerable<bool>>, Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>>(
                            (Tuple<IGrouping<object, object>, IEnumerable<bool>> t) =>
                                new Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>(
                                    t,
                                    t.Item1.OfType<string>()))
                        .Select<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, Tuple<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, IEnumerable<Tuple<bool, string>>>>(
                            (Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>> t) =>
                                new Tuple<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, IEnumerable<Tuple<bool, string>>>(
                                    t,
                                    t.Item1.Item2.Zip<bool, string, Tuple<bool, string>>(
                                        t.Item2,
                                        (bool x, string y) => new Tuple<bool, string>(x, y))))
                        .SelectMany<Tuple<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, IEnumerable<Tuple<bool, string>>>, Tuple<bool, string>, string>(
                            (Tuple<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, IEnumerable<Tuple<bool, string>>> t) =>
                                t.Item2,
                            (Tuple<Tuple<Tuple<IGrouping<object, object>, IEnumerable<bool>>, IEnumerable<string>>, IEnumerable<Tuple<bool, string>>> t, Tuple<bool, string> t0) =>
                                t0.Item1 ? t0.Item2 : ""null"")"),
                StripWhitespace(csharp)
                );
Esempio n. 24
0
            public override Expression Normalize(Expression expression)
            {
                //
                // NB: Typical Reaqtor clients talk to some service APIs on a front-end service that does
                //     further analysis of the expression tree (after deserialization) prior to sending it
                //     to one or more query evaluator nodes. For example, a query may get split to run across
                //     multiple nodes. Here, we bind directly to the query engine, so a few more steps are
                //     involved to make this happen:
                //
                //     - The engine stores definitions in "tuple normal form" such that all operators can be
                //       defined as unary. E.g. t => t.Item1.Where(t.Item2) rather than (xs, f) => xs.Where(f).
                //     - The client refers to types in the IReactive*Proxy space with async APIs but the
                //       engine has synchronous symmetric APIs in the IReactive* space. We map types across.
                //

                var normalized = base.Normalize(expression);

                var erased = AnonymousTypeTupletizer.Tupletize(normalized, Expression.Constant(null), excludeVisibleTypes: true);

                return(erased);
            }
Esempio n. 25
0
        public void ExpressionMemberAllowListScanner_ManOrBoyTest1()
        {
            var ws = new ExpressionMemberAllowListScanner
            {
                DeclaringTypes =
                {
                    typeof(Queryable),
                    typeof(string),
                    typeof(int),
                    typeof(Tuple <,   >),
                }
            };

            var e = (from x in new[] { 1, 2, 3 }.AsQueryable()
                     where x > 0
                     let y = x * x
                             let z = x.ToString()
                                     select z.ToUpper())
                    .Expression;

            e = AnonymousTypeTupletizer.Tupletize(e, Expression.Constant(value: null));

            Assert.AreSame(e, ws.Visit(e));
        }