Пример #1
0
        public void TypeSubstitutionExpressionVisitor_NewArrayInit_Simple()
        {
            var subst = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type> {
                { typeof(string), typeof(bool) }
            });

            var expA = Expression.NewArrayInit(typeof(string), Expression.Parameter(typeof(string), "e1"), Expression.Parameter(typeof(string), "e2"));
            var expB = Expression.NewArrayInit(typeof(int), Expression.Parameter(typeof(int), "e1"), Expression.Parameter(typeof(int), "e2"));

            var res1 = subst.Apply(expA);
            var res2 = subst.Apply(expB);

            AssertEqual(res1, Expression.NewArrayInit(typeof(bool), Expression.Parameter(typeof(bool), "e1"), Expression.Parameter(typeof(bool), "e2")));
            Assert.AreSame(expB, res2);
        }
Пример #2
0
        public void TypeSubstitutionExpressionVisitor_NewArrayBounds_Simple()
        {
            var subst = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type> {
                { typeof(string), typeof(bool) }
            });

            var expA = Expression.NewArrayBounds(typeof(string), Expression.Constant(1));
            var expB = Expression.NewArrayBounds(typeof(int), Expression.Constant(1));

            var res1 = subst.Apply(expA);
            var res2 = subst.Apply(expB);

            AssertEqual(res1, Expression.NewArrayBounds(typeof(bool), Expression.Constant(1)));
            Assert.AreSame(expB, res2);
        }
        /// <summary>
        /// Casts expressions containing reactive interface types to metadata entity types.
        /// </summary>
        /// <param name="expression">The expression to replace types in.</param>
        /// <returns>The expression with interface types replaced by metadata entity types.</returns>
        private static Expression CastExpression(Expression expression)
        {
            var subst = new TypeSubstitutionExpressionVisitor(new Dictionary<Type, Type>
            {
                { typeof(TMetadataInterface), typeof(TMetadataEntity) },
            });

            var result = subst.Apply(expression);

            return result;
        }
Пример #4
0
        public void TypeSubstitutionExpressionVisitor_Anonymize()
        {
            var pers  = typeof(Person);
            var query = (Expression <Func <IEnumerable <Person>, IEnumerable <string> > >)(xs => from x in xs where x.Age > 10 let name = x.Name where name.StartsWith("B") select name.ToUpper() + " is " + x.Age);

            var check1 = new TypeErasureChecker(new[] { typeof(Person) });

            Assert.ThrowsException <InvalidOperationException>(() => check1.Visit(query));


            var anon = RuntimeCompiler.CreateAnonymousType(new[]
            {
                new KeyValuePair <string, Type>("Name", typeof(string)),
                new KeyValuePair <string, Type>("Age", typeof(int)),
            });

            var subst1 = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type>
            {
                { pers, anon }
            });

            var res1 = subst1.Apply(query);

            check1.Visit(res1);

            var check2 = new TypeErasureChecker(new[] { anon });

            Assert.ThrowsException <InvalidOperationException>(() => check2.Visit(res1));


            var f = ((LambdaExpression)res1).Compile();

            var cast       = ((MethodInfo)ReflectionHelpers.InfoOf(() => Enumerable.Cast <int>(null))).GetGenericMethodDefinition().MakeGenericMethod(anon);
            var peopleObj  = new[] { Activator.CreateInstance(anon, new object[] { "Bart", 10 }), Activator.CreateInstance(anon, new object[] { "Lisa", 8 }), Activator.CreateInstance(anon, new object[] { "Bart", 21 }) };
            var peopleAnon = cast.Invoke(obj: null, new object[] { peopleObj });
            var qres       = (IEnumerable <string>)f.DynamicInvoke(peopleAnon);

            Assert.IsTrue(new[] { "BART is 21" }.SequenceEqual(qres));

            var subst2 = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type>
            {
                { anon, pers }
            });

            var res2 = subst2.Apply(res1);

            check2.Visit(res2);

            Assert.ThrowsException <InvalidOperationException>(() => check1.Visit(res2));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(query, res2));
        }
Пример #5
0
        public void TypeSubstitutionExpressionVisitor_ConstantChange_Fail()
        {
            Expression <Func <int> > f = () => 42;

            var subst = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type>
            {
                { typeof(int), typeof(long) }
            });

            Assert.ThrowsException <InvalidOperationException>(() => subst.Apply(f));
        }
Пример #6
0
            /// <summary>
            /// Rewrites a stream to an untyped stream if the stream definition
            /// is closed over wildcard types, and the stream factory returns
            /// an untyped stream.
            /// </summary>
            /// <param name="key">The stream identifier.</param>
            /// <param name="expr">The stream expression.</param>
            /// <returns>
            /// The stream expression with types rewritten to the untyped stream
            /// variant if the expression meets the expected criteria.
            /// </returns>
            private Expression RewriteQuotedReactiveStreamToUntyped(string key, Expression expr)
            {
                // Search for free variables
                var freeVariables = FreeVariableScanner.Scan(expr).ToArray();

                // For now, with the absence of stream factory operators, it is safe to
                // throw if there is more than one free variable as all stream expressions
                // will be invocations of exactly one unbound stream factory parameter.
                if (freeVariables.Length > 1)
                {
                    throw new InvalidOperationException(
                              string.Format(CultureInfo.InvariantCulture, "Unexpected stream expression '{0}' for key '{1}' on query engine '{2}'.", expr.ToTraceString(), key, _queryEngine.Uri.ToCanonicalString()));
                }

                if (freeVariables.Length == 1)
                {
                    // Find single stream factory parameter expression
                    var streamFactoryParam = freeVariables[0];
                    if (streamFactoryParam != null)
                    {
                        // Resolve stream factory type from metadata
                        if (_queryEngine._registry.SubjectFactories.TryGetValue(streamFactoryParam.Name, out var streamFactoryDefinition))
                        {
                            // TODO: support rewrites based on stream factory classes
                            // If definition is a lambda expression, rewrite to the return type
                            var streamFactoryType = streamFactoryDefinition.Expression.Type;
                            var invokeMethod      = streamFactoryType.GetMethod("Invoke");
                            if (invokeMethod != null && invokeMethod.ReturnType == typeof(IMultiSubject))
                            {
                                var actualStreamType   = expr.Type;
                                var expectedStreamType = invokeMethod.ReturnType;
                                if (actualStreamType != expectedStreamType)
                                {
                                    var substitutionVisitor = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type>
                                    {
                                        { actualStreamType, expectedStreamType }
                                    });

                                    _queryEngine.TraceSource.LazyStream_TypeRewrite(key, actualStreamType, expectedStreamType, _queryEngine.Uri);

                                    return(substitutionVisitor.Apply(expr));
                                }
                            }
                        }
                    }
                }

                return(expr);
            }