Ejemplo n.º 1
0
        public void ExpressionEntityTypeRecordizer_Constants_ReferenceEquality()
        {
            var q = new Qux {
                Baz = 42
            };
            var t = new Tuple <Qux, Qux>(q, q);

            var eta = new ExpressionEntityTypeRecordizer();

            var res = eta.Apply(Expression.Constant(t));

            Assert.IsNotNull(res);
            Assert.IsTrue(res.Type.IsGenericType);
            Assert.AreEqual(typeof(Tuple <,>), res.Type.GetGenericTypeDefinition());

            var a1 = res.Type.GetGenericArguments()[0];
            var a2 = res.Type.GetGenericArguments()[1];

            Assert.AreEqual(a1, a2);

            Assert.AreEqual(ExpressionType.Constant, res.NodeType);
            var c = (ConstantExpression)res;
            var o = c.Value;

            var t1 = res.Type.GetProperty("Item1").GetValue(o);
            var t2 = res.Type.GetProperty("Item2").GetValue(o);

            Assert.AreSame(t1, t2);

            Assert.AreEqual(42, t1.GetType().GetProperty("baz").GetValue(t1));
        }
Ejemplo n.º 2
0
        public void ExpressionEntityTypeRecordizer_Constants_ManOrBoy1()
        {
            var c = Expression.Constant(new A {
                B = new B {
                    Cs = new C[] { new C {
                                       D = 42, Es = new List <E> {
                                           new E {
                                               F = 42
                                           }
                                       }
                                   } }
                }
            });

            var eta = new ExpressionEntityTypeRecordizer();

            var res = eta.Apply(c);

            Assert.AreNotEqual(res.Type, c.Type);

            dynamic d = ((ConstantExpression)res).Value;

            int x = d.b.cs[0].d;

            Assert.AreEqual(42, x);
        }
Ejemplo n.º 3
0
        public void ExpressionEntityTypeRecordizer_Constants_Null()
        {
            var eta = new ExpressionEntityTypeRecordizer();

            var res = eta.Apply(Expression.Constant(value: null, typeof(Qux)));

            Assert.IsNotNull(res); // TODO: semantic equivalence checks
            Assert.IsTrue(res is ConstantExpression);
            Assert.IsNull(((ConstantExpression)res).Value);
        }
Ejemplo n.º 4
0
        public void ExpressionEntityTypeRecordizer_Constants_Errors1()
        {
            foreach (var o in new object[]
            {
                new Func <Qux, Qux>(x => x),
            })
            {
                var eta = new ExpressionEntityTypeRecordizer();

                Assert.ThrowsException <InvalidOperationException>(() => eta.Apply(Expression.Constant(o)));
            }
        }
        public void ExpressionEntityTypeRecordizer_Simple()
        {
            var netrc = new NoEntityTypesRemainingChecker();

            foreach (var e in new Expression[]
            {
                (Expression <Func <Qux, int> >)(q => q.Baz),
#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <Qux> >)(() => new Qux()),
                (Expression <Func <Qux> >)(() => new Qux()
                {
                    Baz = 1
                }),
                (Expression <Func <Qux> >)(() => new Qux(1)
                {
                    Foo = "bar"
                }),
                (Expression <Func <Bar> >)(() => new Bar {
                    Foos = new Foo[] { new Foo {
                                           Qux = new Tuple <Func <List <Qux>, long>, bool>(t => t.Count, false)
                                       } }
                }),
                (Expression <Func <IQueryable <Bar>, IQueryable <long> > >)(xs => from x in xs from y in x.Foos where y.Qux.Item2 select y.Qux.Item1(new List <Qux> {
                    new Qux(1)
                    {
                        Foo = "bar"
                    }
                })),
                (Expression <Func <IQueryable <Bar>, IQueryable <Foo> > >)(xs => from x in xs from y in x.Foos select y),
                (Expression <Func <Qux> >)(() => Activator.CreateInstance <Qux>()),
                (Expression <Action>)(() => FooIt <Qux>()),
                (Expression <Func <Qux[]> >)(() => new Qux[1]),
                (Expression <Func <Qux[]> >)(() => new Qux[] { new Qux(1), new Qux {
                                                                   Baz = 1
                                                               } }),
                (Expression <Func <Tuple <Qux, int> > >)(() => new Tuple <Qux, int>(new Qux(1), 2)),
                (Expression <Func <Holder <Qux> > >)(() => new Holder <Qux> {
                    Value = new Qux(42)
                }),
#pragma warning restore IDE0004 // Remove Unnecessary Cast
            })
            {
                var eta = new ExpressionEntityTypeRecordizer();

                var res = eta.Apply(e);

                netrc.Visit(res);

                var expressionComparer = ObjectComparator.CreateInstance().ExpressionComparator;
                expressionComparer.Equals(e, res);
            }
        }
Ejemplo n.º 6
0
        public void ExpressionEntityTypeRecordizer_Enum3()
        {
            var e = (Expression <Func <Persoon2, bool> >)(p => p.Geslacht == Sex.Male);

            var eta = new ExpressionEntityTypeRecordizer();

            var r = (LambdaExpression)eta.Apply(e);

            var m = (MemberExpression)((UnaryExpression)((BinaryExpression)r.Body).Left).Operand;

            Assert.AreEqual("contoso://entities/person/sex", m.Member.Name);
            Assert.AreEqual(typeof(int?), ((PropertyInfo)m.Member).PropertyType);
        }
Ejemplo n.º 7
0
        public void EntityTypeSubstitutor_NestedKnownTypeResolutionSuccess()
        {
            // KT is a `KnownType`; KT rewriting should be successful.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <KT> >)(() => new KT(new KT()));

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1 })
                {
                    Assert.AreSame(e, s.Apply(e));  // no exception, thus rewriting was successful
                }
            }
        }
Ejemplo n.º 8
0
        public void ExpressionEntityTypeRecordizer_Enum3_Nullable2()
        {
            var p = Expression.Parameter(typeof(Persoon2));
            var e = Expression.Equal(Expression.Property(p, "Geslacht"), Expression.Constant(value: null, typeof(Sex?)));

            var eta = new ExpressionEntityTypeRecordizer();

            var r = (BinaryExpression)eta.Apply(e);

            var m = (MemberExpression)r.Left;
            var c = (ConstantExpression)r.Right;

            Assert.AreEqual("contoso://entities/person/sex", m.Member.Name);
            Assert.AreEqual(typeof(int?), ((PropertyInfo)m.Member).PropertyType);
            Assert.AreEqual(typeof(int?), c.Type);
            Assert.IsNull(c.Value);
        }
Ejemplo n.º 9
0
        public void EntityTypeSubstitutor_MemberMemberBindingNonKTSuccess()
        {
            // `Grmbl` is not attributed with `KnownType`, but the expression hook does not pick it up
            // in the member member bindings. Expression is thus rewritten successfully. Note this
            // fails if you use the `Grmbl` constructor instead.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <F> >)(() => new F(new KT {
                GrmblProperty = { X = 1 }
            }));

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                Assert.AreSame(e1, s.Apply(e1));
            }
        }
Ejemplo n.º 10
0
        public void ExpressionEntityTypeRecordizer_Enum2()
        {
            var e = (Expression <Func <Persoon1, Persoon1> >)(x => x);

            var eta = new ExpressionEntityTypeRecordizer();

            var r = (LambdaExpression)eta.Apply(e);

            var t = r.Parameters.Single().Type;

            Assert.IsTrue(t.IsRecordType());

            var ps = t.GetProperties();
            var s  = ps.Single(p => p.Name == "contoso://entities/person/sex");

            Assert.AreEqual(typeof(int), s.PropertyType);
        }
Ejemplo n.º 11
0
        public void EntityTypeSubstitutor_NestedKnownTypeResolutionFailure()
        {
            // Grmbl is not a `KnownType`; non-KTs are disallowed due to type erasure.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <KT> >)(() => new KT(new KT(new Grmbl())));
            var e2 = (Expression <Func <KT, Grmbl> >)((KT kt) => kt._kt._grmbl);

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1, e2 })
                {
                    // rewrite unsuccessful
                    AssertEx.ThrowsException <InvalidOperationException>(() => s.Apply(e), ex => Assert.IsTrue(ex.Message.Contains("Grmbl")));
                }
            }
        }
Ejemplo n.º 12
0
        public void EntityTypeSubstitutor_MemberMemberBindingSuccess()
        {
            // Member member binding with `KnownType`s should result in no rewrite.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <F> >)(() => new F(new KT {
                KTProperty = { KTProperty = { X = 1 } }
            }));

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1 })
                {
                    Assert.AreSame(e, s.Apply(e));  // no exception, thus rewriting was successful
                }
            }
        }
Ejemplo n.º 13
0
        public void ExpressionEntityTypeRecordizer_Errors()
        {
            foreach (var e in new Expression[]
            {
                (Expression <Func <Qux> >)(() => new Qux(1)
                {
                    Baz = 1
                }),
                (Expression <Func <MissingMapping> >)(() => new MissingMapping(1)),
                (Expression <Func <NonMatchingMapping> >)(() => new NonMatchingMapping(1)),
                (Expression <Func <DuplicateMapping> >)(() => new DuplicateMapping(1, 2)),
            })
            {
                var eta = new ExpressionEntityTypeRecordizer();

                Assert.ThrowsException <InvalidOperationException>(() => eta.Apply(e));
            }
        }
        public void ExpressionEntityTypeRecordizer_Constants_Simple()
        {
            var recType = RuntimeCompiler.CreateRecordType(new[] {
                new KeyValuePair <string, Type>("a", typeof(int)),
                new KeyValuePair <string, Type>("b", typeof(Qux))
            }, valueEquality: true);

            var rec = Activator.CreateInstance(recType);

            recType.GetProperty("a").SetValue(rec, 42);
            recType.GetProperty("b").SetValue(rec, new Qux(43));

            foreach (var o in new object[]
            {
                new Qux(),
                new Qux(1),
                new Qux(1)
                {
                    Foo = "bar"
                },
                new Qux[1],
                new Qux[] { new Qux(1), new Qux(2) },
                new List <Qux> {
                    new Qux(1), new Qux(2)
                },
                new Func <int, int>(x => x),
                42,
                "bar",
                (Expression <Func <Qux, Qux> >)(x => x),
#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <Qux[]> >)(() => new Qux[] { new Qux(123) }),
#pragma warning restore IDE0004 // Remove Unnecessary Cast
                new Tuple <Qux, int>(new Qux(), 42),
                new { a = 1, b = new Qux(42), c = "bar" },
                rec,
            })
            {
                var eta = new ExpressionEntityTypeRecordizer();

                var res = (ConstantExpression)eta.Apply(Expression.Constant(o));

                Assert.IsTrue(ObjectComparator.CreateInstance().Equals(o, res.Value));
            }
        }
Ejemplo n.º 15
0
        public void ExpressionEntityTypeRecordizer_Enum4()
        {
            var e = (Expression <Func <Persoon3, bool> >)(p => p.Geslacht == Sex.Male && p.Color == ConsoleColor.Blue && Console.ForegroundColor == ConsoleColor.Red);

            var eta = new ExpressionEntityTypeRecordizer();

            var r = (LambdaExpression)eta.Apply(e);

            var t = r.Parameters.Single().Type;

            Assert.IsTrue(t.IsRecordType());

            var ps = t.GetProperties();
            var s1 = ps.Single(p => p.Name == "contoso://entities/person/sex");
            var s2 = ps.Single(p => p.Name == "contoso://entities/person/color");

            Assert.AreEqual(typeof(int), s1.PropertyType);
            Assert.AreEqual(typeof(ConsoleColor), s2.PropertyType);
        }
Ejemplo n.º 16
0
        public void EntityTypeSubstitutor_ResolutionFailures()
        {
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <F> >)(() => new F(new Grmbl()));
            var e2 = (Expression <Func <F, Grmbl> >)((F f) => f.GrmblProperty);
            var e3 = (Expression <Func <F, Grmbl> >)((F f) => f.GrmblMethod());
            var e4 = (Expression <Func <F, Grmbl> >)((F f) => f.grmblMember);
            var e5 = (Expression <Func <F, Grmbl> >)((F f) => f[0]);

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1, e2, e3, e4, e5 })
                {
                    AssertEx.ThrowsException <InvalidOperationException>(() => s.Apply(e), ex => Assert.IsTrue(ex.Message.Contains("Grmbl")));
                }
            }
        }
Ejemplo n.º 17
0
        public void EntityTypeSubstitutor_KnownTypeResolutionSuccess()
        {
            // KT is a `KnownType`; KT rewriting should be successful.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <F> >)(() => new F(new KT()));
            var e2 = (Expression <Func <F, KT> >)((F f) => f.KTProperty);
            var e3 = (Expression <Func <F, KT> >)((F f) => f.KTMethod());
            var e4 = (Expression <Func <F, KT> >)((F f) => f.ktMember);
            var e5 = (Expression <Func <F, KT> >)((F f) => f[0.0]);

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1, e2, e3, e4, e5 })
                {
                    var rewr = s.Apply(e);  // no exception, thus rewriting was successful
                }
            }
        }
        public void ExpressionEntityTypeRecordizer_Errors()
        {
            foreach (var e in new Expression[]
            {
#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <Qux> >)(() => new Qux(1)
                {
                    Baz = 1
                }),
                (Expression <Func <MissingMapping> >)(() => new MissingMapping(1)),
                (Expression <Func <NonMatchingMapping> >)(() => new NonMatchingMapping(1)),
                (Expression <Func <DuplicateMapping> >)(() => new DuplicateMapping(1, 2)),
#pragma warning restore IDE0004 // Remove Unnecessary Cast
            })
            {
                var eta = new ExpressionEntityTypeRecordizer();

                Assert.ThrowsException <InvalidOperationException>(() => eta.Apply(e));
            }
        }
Ejemplo n.º 19
0
        public void EntityTypeSubstitutor_ResolutionFailureInKnownTypeConstructor()
        {
            // Grmbl is not a `KnownType`; non-KTs are disallowed due to type erasure.
            var eta = new ExpressionEntityTypeAnonymizer();
            var etr = new ExpressionEntityTypeRecordizer();

            var e1 = (Expression <Func <KT> >)(() => new KT(new Grmbl()));
            var e2 = (Expression <Func <KT, Grmbl> >)((KT kt) => kt.GrmblProperty);
            var e3 = (Expression <Func <KT, Grmbl> >)((KT kt) => kt.GrmblMethod());
            var e4 = (Expression <Func <KT, Grmbl> >)((KT kt) => kt.grmblMember);
            var e5 = (Expression <Func <KT, Grmbl> >)((KT kt) => kt[0]);

            foreach (var s in new ExpressionEntityTypeSubstitutor[] { eta, etr })
            {
                foreach (var e in new Expression[] { e1, e2, e3, e4, e5 })
                {
                    AssertEx.ThrowsException <InvalidOperationException>(() => s.Apply(e), ex => Assert.IsTrue(ex.Message.Contains("Grmbl")));
                }
            }
        }
Ejemplo n.º 20
0
        public void ExpressionEntityTypeRecordizer_Constants_ManOrBoy3()
        {
            var c = new QuotedExpressionHolder {
                E = () => new E {
                    F = 42
                }.Equals(new E {
                    F = 42
                })
            };

            var eta = new ExpressionEntityTypeRecordizer();

            var res = (ConstantExpression)eta.Apply(Expression.Constant(c));

            // The type `E` uses reference equality, as it does not overload `Equals`.
            Assert.IsFalse(c.E.Compile().Invoke());
            var property = res.Value.GetType().GetProperty("expression");

            // The generated record type for `E` does have value equality based on its properties.
            Assert.IsTrue(((Expression <Func <bool> >)property.GetValue(res.Value)).Compile().Invoke());
        }
        private static Expression Roundtrip(Expression e, bool skipBonsaiStringEqualityAssert = false)
        {
            var helper             = new SerializationHelper((lf, rf) => new RecordizingBonsaiSerializer(lf, rf));
            var originalHelper     = new SerializationHelper();
            var originalRecordizer = new ExpressionEntityTypeRecordizer();

            var stream = new MemoryStream();

            helper.Serialize(e, stream);

            var originalStream = new MemoryStream();

            originalHelper.Serialize(originalRecordizer.Apply(e), originalStream);

            if (!skipBonsaiStringEqualityAssert)
            {
                Assert.AreEqual(Encoding.UTF8.GetString(originalStream.ToArray()), Encoding.UTF8.GetString(stream.ToArray()));
            }

            stream.Position = 0;
            return(helper.Deserialize <Expression>(stream));
        }
Ejemplo n.º 22
0
        public void ExpressionEntityTypeRecordizer_Constants_ManOrBoy2()
        {
            Expression <Func <IEnumerable <A>, IEnumerable <int> > > f = xs => from x in xs
                                                                         let b = x.B
                                                                                 from c in b.Cs
                                                                                 let d = c.D
                                                                                         where d > 0
                                                                                         let e = new A {
                B = new B {
                    Cs = new C[] { c, new C {
                                       D = d + 1, Es = new List <E> {
                                           new E {
                                               F = d * d
                                           }
                                       }
                                   } }
                }
            }
            let z = new A {
                B = { Cs                                         = new C[] { c, new C {
                                                                                 D                       = d + 1, Es ={ new E {
                                                                                                                         F = d * d
                                                                                                                     } }
                                                                             } } }
            }
            where e.B.Cs[1].Es[0].F == z.B.Cs[1].Es[0].F
            select 7 * e.B.Cs.Sum(y => y.D);

            var g = f.Compile();

            var res = g(new[] {
                new A {
                    B = new B {
                        Cs = new C[] { new C {
                                           D = 23
                                       } }
                    }
                },
                new A {
                    B = new B {
                        Cs = new C[] { new C {
                                           D = -1
                                       } }
                    }
                },
                new A {
                    B = new B {
                        Cs = new C[] { new C {
                                           D = 87
                                       } }
                    }
                },
            });

            var eta = new ExpressionEntityTypeRecordizer();

            var h = (LambdaExpression)eta.Apply(f);

            var anonA  = h.Parameters[0].Type.GetGenericArguments()[0];
            var propB  = anonA.GetProperty("b");
            var anonB  = propB.PropertyType;
            var propCs = anonB.GetProperty("cs");
            var anonC  = propCs.PropertyType.GetElementType();
            var propD  = anonC.GetProperty("d");

            var c23 = Activator.CreateInstance(anonC);

            propD.SetValue(c23, 23);
            var cm1 = Activator.CreateInstance(anonC);

            propD.SetValue(cm1, -1);
            var c87 = Activator.CreateInstance(anonC);

            propD.SetValue(c87, 87);

            var cs23 = (IList)Array.CreateInstance(anonC, 1);

            cs23[0] = c23;
            var csm1 = (IList)Array.CreateInstance(anonC, 1);

            csm1[0] = cm1;
            var cs87 = (IList)Array.CreateInstance(anonC, 1);

            cs87[0] = c87;

            var b23 = Activator.CreateInstance(anonB);

            propCs.SetValue(b23, cs23);
            var bm1 = Activator.CreateInstance(anonB);

            propCs.SetValue(bm1, csm1);
            var b87 = Activator.CreateInstance(anonB);

            propCs.SetValue(b87, cs87);

            var a23 = Activator.CreateInstance(anonA);

            propB.SetValue(a23, b23);
            var am1 = Activator.CreateInstance(anonA);

            propB.SetValue(am1, bm1);
            var a87 = Activator.CreateInstance(anonA);

            propB.SetValue(a87, b87);

            var inp = (IList)Array.CreateInstance(anonA, 3);

            inp[0] = a23;
            inp[1] = am1;
            inp[2] = a87;

            var p = CompilerGeneratedNameEliminator.Prettify(h).ToCSharpString(allowCompilerGeneratedNames: true).Replace("<>a__RecordType", "rec").Replace("<>h__TransparentIdentifier", "__t");

            Assert.IsTrue(true, p);

            var output = (IEnumerable <int>)h.Compile().DynamicInvoke(new object[] { inp });

            Assert.IsTrue(res.SequenceEqual(output));
        }
Ejemplo n.º 23
0
        public void ExpressionEntityTypeRecordizer_ArgumentChecking()
        {
            var etr = new ExpressionEntityTypeRecordizer();

            AssertEx.ThrowsException <ArgumentNullException>(() => etr.Apply(expression: null), ex => Assert.AreEqual("expression", ex.ParamName));
        }