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); } } }
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); }
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)); }
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); }
public ReplaceTypeParamImplementationsExpressionType(ImmutableConcretion typeParams, ExpressionTransformation <Core.ExpressionKindTransformation, ReplaceTypeParamImplementationsExpressionType> expr) : base(expr) { TypeParams = typeParams; }