Example #1
0
        public void Should_not_break_for_invalid_input()
        {
            var input  = "some string";
            var source = Observable.Return(input);
            var expressionExpectingColor = "value.B > value.R && value.B > value.G ? \"Bluish\" : \"Something else\"";

            var options = new ExpressionTransformationOptions()
            {
                Expression = expressionExpectingColor
            };

            var transformation = new ExpressionTransformation <string>(options);

            var scheduler = new TestScheduler();

            var actual = scheduler.Start(
                () => transformation.GetOperator()(source),
                created: 0,
                subscribed: 10,
                disposed: 100
                );

            var expected = new Recorded <Notification <string> >[] {
                OnCompleted <string>(10)
            };

            ReactiveAssert.AreElementsEqual(expected, actual.Messages);
        }
        /// <summary>
        /// Registers the specified <see cref="IExpressionTransformer{T}"/> for the transformer's
        /// <see cref="IExpressionTransformer{T}.SupportedExpressionTypes"/>. If <see cref="IExpressionTransformer{T}.SupportedExpressionTypes"/>
        /// returns <see langword="null" />, the <paramref name="transformer"/> is registered as a generic transformer which will be applied to all
        /// <see cref="Expression"/> nodes.
        /// </summary>
        /// <typeparam name="T">The type of expressions handled by the <paramref name="transformer"/>. This should be a type implemented by all
        /// expressions identified by <see cref="IExpressionTransformer{T}.SupportedExpressionTypes"/>. For generic transformers, <typeparamref name="T"/>
        /// must be <see cref="Expression"/>.</typeparam>
        /// <param name="transformer">The transformer to register.</param>
        /// <remarks>
        /// <para>
        /// The order in which transformers are registered is the same order on which they will later be applied by
        /// <see cref="TransformingExpressionTreeVisitor"/>. When more than one transformer is registered for a certain <see cref="ExpressionType"/>,
        /// each of them will get a chance to transform a given <see cref="Expression"/>, until the first one returns a new <see cref="Expression"/>.
        /// At that point, the transformation will start again with the new <see cref="Expression"/> (and, if the expression's type has changed, potentially
        /// different transformers).
        /// </para>
        /// <para>
        /// When generic transformers are registered, they act as if they had been registered for all <see cref="ExpressionType"/> values (including
        /// custom ones). They will be applied in the order registered, but only after all respective specific transformers have run (without modifying
        /// the expression, which would restart the transformation process with the new expression as explained above).
        /// </para>
        /// <para>
        /// When an <see cref="IExpressionTransformer{T}"/> is registered for an incompatible <see cref="ExpressionType"/>, this is not detected until
        /// the transformer is actually applied to an <see cref="Expression"/> of that <see cref="ExpressionType"/>.
        /// </para>
        /// </remarks>
        public void Register <T> (IExpressionTransformer <T> transformer) where T : Expression
        {
            ArgumentUtility.CheckNotNull("transformer", transformer);

            ExpressionTransformation transformation = expr => TransformExpression(expr, transformer);

            if (transformer.SupportedExpressionTypes == null)
            {
                if (typeof(T) != typeof(Expression))
                {
                    var message = string.Format(
                        "Cannot register an IExpressionTransformer<{0}> as a generic transformer. Generic transformers must implement "
                        + "IExpressionTransformer<Expression>.",
                        typeof(T).Name);
                    throw new ArgumentException(message, "transformer");
                }

                _genericTransformations.Add(transformation);
            }
            else
            {
                foreach (var expressionType in transformer.SupportedExpressionTypes)
                {
                    _transformations.Add(expressionType, transformation);
                }
            }
        }
Example #3
0
        public void Should_expose_input_value_in_context()
        {
            var input  = "Bruce";
            var source = Observable.Return(input);

            var options = new ExpressionTransformationOptions()
            {
                Expression = "\"Hello \" + value"
            };

            var transformation = new ExpressionTransformation <string>(options);

            var scheduler = new TestScheduler();

            var actual = scheduler.Start(
                () => transformation.GetOperator()(source),
                created: 0,
                subscribed: 10,
                disposed: 100
                );

            var expected = new Recorded <Notification <string> >[] {
                OnNext(10, "Hello Bruce"),
                OnCompleted <string>(10)
            };

            ReactiveAssert.AreElementsEqual(expected, actual.Messages);
        }
Example #4
0
        public void Should_allow_usage_of_color_related_extensions_methods()
        {
            var input = new Dictionary <string, DeviceState>()
            {
                { "Copperhead", new DeviceState(new Color[] { Color.Red }) }
            };
            var source = Observable.Return(input);
            var expressionExpectingColor = "value[\"Copperhead\"].Colors.Cast().First().ToCommaSeparatedRgbString()";
            var expectation = "255,0,0";

            var options = new ExpressionTransformationOptions()
            {
                Expression = expressionExpectingColor
            };

            var transformation = new ExpressionTransformation <string>(options);

            var scheduler = new TestScheduler();

            var actual = scheduler.Start(
                () => transformation.GetOperator()(source),
                created: 0,
                subscribed: 10,
                disposed: 100
                );

            var expected = new Recorded <Notification <string> >[] {
                OnNext(10, expectation),
                OnCompleted <string>(10)
            };

            ReactiveAssert.AreElementsEqual(expected, actual.Messages);
        }
        private void CheckTransformationMatchesTransformer <T> (
            ExpressionTransformation transformation,
            IExpressionTransformer <T> expectedTransformer)
            where T : Expression
        {
            var transformationResult = transformation(null);
            var expectedResult       = expectedTransformer.Transform(null);

            Assert.That(transformationResult, Is.SameAs(expectedResult));
        }
Example #6
0
        public void Should_allow_expressions_on_non_primitive_values(string expectation, int index)
        {
            var colors = new Color[]
            {
                Color.AliceBlue,
                Color.Blue,
                Color.BlueViolet,
                Color.Green,
                Color.DarkGreen,
                Color.DarkOliveGreen,
                Color.Red,
                Color.DarkRed,
                Color.DarkOrange
            };


            var input  = new Ref <Color>(colors[index]);
            var source = Observable.Return(input);

            var options = new ExpressionTransformationOptions()
            {
                Expression = "value.B > value.R && value.B > value.G ? \"Bluish\" : (value.G > value.B && value.G > value.R ? \"Greenish\" : \"Redish\")"
            };

            var transformation = new ExpressionTransformation <string>(options);

            var scheduler = new TestScheduler();

            var actual = scheduler.Start(
                () => transformation.GetOperator()(source),
                created: 0,
                subscribed: 10,
                disposed: 100
                );

            var expected = new Recorded <Notification <string> >[] {
                OnNext(10, expectation),
                OnCompleted <string>(10)
            };

            ReactiveAssert.AreElementsEqual(expected, actual.Messages);
        }
Example #7
0
 public ReplaceTypeParamImplementationsExpressionType(ImmutableConcretion typeParams, ExpressionTransformation <Core.ExpressionKindTransformation, ReplaceTypeParamImplementationsExpressionType> expr) : base(expr)
 {
     TypeParams = typeParams;
 }