Click here to Skip to main content
15,888,527 members
Articles / Programming Languages / C# 4.0

Parameter Substitution within Expression Trees

Rate me:
Please Sign up or sign in to vote.
4.95/5 (27 votes)
6 Jan 2011CPOL6 min read 53.5K   409   26  
This article describes how to substitute a parameter within an Expression tree by another expression, similar to how one can substitute an argument within a mathematical function by a different function
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Linq.Expressions;
using ExpressionModifier;

namespace SimplePlots
{
    public partial class MainPage : UserControl
    {
        public const double AXIS_LENGTH = 500d;
        public const double AXIS_UNIT = 25d;

        public MainPage()
        {
            InitializeComponent();

            YAxis.Y2 = AXIS_LENGTH;
            XAxis.X2 = AXIS_LENGTH;
            XMarks.Width = AXIS_LENGTH;
            YMarks.Height = AXIS_LENGTH;

            SetAxes();
            
            // uncomment the two lines below for a sinusoidal example
            PlotMainAndModified(x => Math.Sin(-x), x => x * 2 + 3, 0.01, 10d);
            AddPlot(Colors.Yellow, 0.01, x =>Math.Sin(-(x * 2 + 3)), 3d);

            /*
            // uncomment the two lines below for a parabola example
            PlotMainAndModified(x => x * x, x => x * x - 2, 0.01, 10d);
            AddPlot(Colors.Yellow, 0.01, x => (x * x - 2) * (x * x - 2), 3d);
            */
        }

        public void PlotMainAndModified(Expression<Func<double, double>> mainExpression, Expression<Func<double, double>> substExpression, double delta = 0.1, double pointSize = POINT_SIZE)
        {
            AddPlot(Colors.Red, delta, mainExpression.Compile(), pointSize);

            LambdaExpression modifiedExpression =
                mainExpression.Substitute("x", substExpression);

            AddPlot(Colors.Blue, 0.01, modifiedExpression.Compile() as Func<double, double>, pointSize);
        }

        void SetAxes()
        {
            XMarks.Children.Clear();
            YMarks.Children.Clear();

            int currentNumber = (int) -(AXIS_LENGTH / AXIS_UNIT) / 2;

            for (double x = 0; x <= AXIS_LENGTH; x += AXIS_UNIT)
            {
                Line xMark =
                    new Line
                    {
                        Stroke = new SolidColorBrush(Colors.Black),
                        StrokeThickness = 1,
                        X1 = x,
                        Y1 = -5,
                        X2 = x,
                        Y2 = 0
                    };

                TextBlock xTextBlock = new TextBlock { Text = "" + currentNumber };
                Canvas.SetLeft(xTextBlock, x - 5);

                XMarks.Children.Add(xMark);
                XMarks.Children.Add(xTextBlock);

                double y = AXIS_LENGTH - x;
                Line yMark =
                    new Line
                    {
                        Stroke = new SolidColorBrush(Colors.Black),
                        StrokeThickness = 1,
                        X1 = 5,
                        Y1 = y,
                        X2 = 0,
                        Y2 = y
                    };

                TextBlock yTextBlock = new TextBlock { Text = "" + currentNumber };
                Canvas.SetTop(yTextBlock, y - 10);
                Canvas.SetLeft(yTextBlock, -17);

                YMarks.Children.Add(yMark);
                YMarks.Children.Add(yTextBlock);

                currentNumber++;
            }
        }
                    
        const double POINT_SIZE = 5;

        void AddPoint(double x, double y, Color color, double pointSize = POINT_SIZE)
        {

            Ellipse point = 
                new Ellipse 
                { 
                    Fill = new SolidColorBrush(color),
                    Width = pointSize,
                    Height = pointSize 
                };

            Canvas.SetLeft(point, x * 25 - pointSize / 2d);
            Canvas.SetTop(point, -y * 25 - pointSize / 2d);

            Plots.Children.Add(point);
        }

        public void AddPlot(Color color, double delta, Func<double, double> function, double pointSize)
        {
            double minX = -(AXIS_LENGTH / AXIS_UNIT) / 2;
            double maxX = -minX;

            for (double currentX = minX; currentX <= maxX; currentX += delta)
            {
                try
                {
                    double y = function(currentX);
                    AddPoint(currentX, y, color, pointSize);
                }
                catch
                {
                    
                }
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect AWebPros
United States United States
I am a software architect and a developer with great passion for new engineering solutions and finding and applying design patterns.

I am passionate about learning new ways of building software and sharing my knowledge with others.

I worked with many various languages including C#, Java and C++.

I fell in love with WPF (and later Silverlight) at first sight. After Microsoft killed Silverlight, I was distraught until I found Avalonia - a great multiplatform package for building UI on Windows, Linux, Mac as well as within browsers (using WASM) and for mobile platforms.

I have my Ph.D. from RPI.

here is my linkedin profile

Comments and Discussions