Monday, March 27, 2006

Illustration of the Linq "Expressions Tree" and of the former classes

As an illustration of what is an Linq "Expression Tree", I will demonstrate here how to go from a simple one line declaration in a source file : Expression < Func < BusinessDAO , IEnumerable >> FunctionExpression = mydata => mydata.Products.Where(p => p.UnitPrice.Length == 4); to a visual representation of that code : As an illustration of the previous post, I managed to go from here to there in two different ways.
  • Once using the "Visitor pattern" to the Expression :

In that case, the tree structure is "implicit" and is handled internally by the visitor logic

  • Once with a classical Tree obtained using the wrapper exposed on the previous post :

Here the tree is accessed direcly on the ExpressionTree object itself, as the role of the wrapper is to explicit the implicit tree structure, and expose it trhough a "children" property. I hope this make it clearer what expressions are.

So now, the interesting question : which usefulness do you envision for them in your projects .....? ;)

[+/-] read/hide the code

Form1.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Expressions;
using System.Query;
using System.Windows.Forms;
using DataStructure;

namespace ExpressionIllustration
{



    public partial class Form1 : Form
    {
        BusinessDAO data;
        public Form1()
        {
            InitializeComponent();
            data = new BusinessDAO();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            Expression<Func<BusinessDAO, IEnumerable>> FunctionExpression =mydata => mydata.Products.Where(p => p.ProductName.Length == 4);

            this.treeView1.Nodes.Clear();
            this.treeView1.Nodes.Add((TreeNode)FunctionExpression.Visit(new ExpressionTreeVisitor.VisitorDelegate(Utils.ToTreeNodeConverter), null));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Expression<Func<BusinessDAO, IEnumerable>> FunctionExpression =mydata => mydata.Products.Where(p => p.ProductName.Length == 4);
            ExpressionTree FunctionExpressionAsaTree = new ExpressionTree(FunctionExpression);

            this.treeView1.Nodes.Clear();
            this.treeView1.Nodes.Add(FunctionExpressionAsaTree.ToTreeNodes());
        }
    }
    public static class Utils
    {
        public static object ToTreeNodeConverter(Expression arg, object param, object[] sonreturn)
        {
            TreeNode ret = new TreeNode("Return Type : " +arg.Type.ToString());
            ret.Nodes.Add(new TreeNode("Expression : " + arg.ToString()));
            ret.Nodes.Add(new TreeNode("Expression Type: " + arg.NodeType.ToString()));
            TreeNode children = new TreeNode("Children");

            foreach (object son in sonreturn)
            {
                object[] group = son as object[];
                if (group != null)
                {
                    foreach (object obj in group)
                        children.Nodes.Add(obj as TreeNode);
                }
                else
                    children.Nodes.Add(son as TreeNode);
            }
         
            if(children.Nodes.Count >0)
                ret.Nodes.Add(children);
            return ret;
        }

        public static TreeNode ToTreeNodes(this ExpressionTree arg)
        {
            TreeNode ret = new TreeNode(arg.Type.ToString());
            ret.Nodes.Add(new TreeNode("Expression : " + arg.Value.ToString()));
            TreeNode children = new TreeNode("Children");

            foreach (ExpressionTree son in arg.Children)
                children.Nodes.Add(son.ToTreeNodes());

            ret.Nodes.Add(children);
            return ret;
        }
    }

    public partial class Product
    {
        private string _ProductName;
        private double _UnitPrice;
        public string ProductName
        {
            get { return _ProductName; }
            set { _ProductName = value; }
        }
        public double UnitPrice
        {
            get { return _UnitPrice; }
            set { _UnitPrice = value; }
        }
    }

    public class BusinessDAO
    {
        Product[] aproducts = new Product[2];

        public BusinessDAO()
        {
            aproducts[0] = new Product { ProductName = "1", UnitPrice = 1 };
            aproducts[1] = new Product { ProductName = "12", UnitPrice = 2 };
        }

        public IEnumerable<Product> Products
        {
            get { return aproducts; }
        }
    }
}
 

0 Comments:

Post a Comment

<< Home