ExpressionPrinter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / ExpressionPrinter.cs / 1305376 / ExpressionPrinter.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq; 
using System.Reflection;
using System.Text; 
 
using System.Data.Common;
using System.Data.Common.Utils; 
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;

namespace System.Data.Common.CommandTrees.Internal 
{
    ///  
    /// Prints a command tree 
    /// 
    internal class ExpressionPrinter : TreePrinter 
    {
        private PrinterVisitor _visitor = new PrinterVisitor();

        internal ExpressionPrinter() 
            : base() {}
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 
        internal string Print(DbExpression expr)
        { 
            Debug.Assert(expr != null, "Null DbExpression");
            return this.Print(_visitor.VisitExpression(expr));
        }
 
        internal string Print(DbDeleteCommandTree tree)
        { 
            // Predicate should not be null since DbDeleteCommandTree initializes it to DbConstantExpression(true) 
            Debug.Assert(tree != null && tree.Predicate != null, "Invalid DbDeleteCommandTree");
 
            TreeNode targetNode;
            if (tree.Target != null)
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            }
            else 
            { 
                targetNode = new TreeNode("Target");
            } 

            TreeNode predicateNode;
            if (tree.Predicate != null)
            { 
                predicateNode = _visitor.VisitExpression("Predicate", tree.Predicate);
            } 
            else 
            {
                predicateNode = new TreeNode("Predicate"); 
            }

            return this.Print(new TreeNode(
                    "DbDeleteCommandTree", 
                    CreateParametersNode(tree),
                    targetNode, 
                    predicateNode)); 
        }
 
        internal string Print(DbFunctionCommandTree tree)
        {
            Debug.Assert(tree != null, "Null DbFunctionCommandTree");
 
            TreeNode funcNode = new TreeNode("EdmFunction");
            if (tree.EdmFunction != null) 
            { 
                funcNode.Children.Add(_visitor.VisitFunction(tree.EdmFunction, null));
            } 

            TreeNode typeNode = new TreeNode("ResultType");
            if (tree.ResultType != null)
            { 
                PrinterVisitor.AppendTypeSpecifier(typeNode, tree.ResultType);
            } 
 
            return this.Print(new TreeNode("DbFunctionCommandTree", CreateParametersNode(tree), funcNode, typeNode));
        } 

        internal string Print(DbInsertCommandTree tree)
        {
            Debug.Assert(tree != null, "Null DbInsertCommandTree"); 

            TreeNode targetNode = null; 
            if (tree.Target != null) 
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            }
            else
            {
                targetNode = new TreeNode("Target"); 
            }
 
            TreeNode clausesNode = new TreeNode("SetClauses"); 
            foreach (DbModificationClause clause in tree.SetClauses)
            { 
                if (clause != null)
                {
                    clausesNode.Children.Add(clause.Print(_visitor));
                } 
            }
 
            TreeNode returningNode = null; 
            if (null != tree.Returning)
            { 
                returningNode = new TreeNode("Returning", _visitor.VisitExpression(tree.Returning));
            }
            else
            { 
                returningNode = new TreeNode("Returning");
            } 
 
            return this.Print(new TreeNode(
                "DbInsertCommandTree", 
                CreateParametersNode(tree),
                targetNode,
                clausesNode,
                returningNode)); 
        }
 
        internal string Print(DbUpdateCommandTree tree) 
        {
            // Predicate should not be null since DbUpdateCommandTree initializes it to DbConstantExpression(true) 
            Debug.Assert(tree != null && tree.Predicate != null, "Invalid DbUpdateCommandTree");

            TreeNode targetNode = null;
            if (tree.Target != null) 
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            } 
            else
            { 
                targetNode = new TreeNode("Target");
            }

            TreeNode clausesNode = new TreeNode("SetClauses"); 
            foreach (DbModificationClause clause in tree.SetClauses)
            { 
                if (clause != null) 
                {
                    clausesNode.Children.Add(clause.Print(_visitor)); 
                }
            }

            TreeNode predicateNode; 
            if (null != tree.Predicate)
            { 
                predicateNode = new TreeNode("Predicate", _visitor.VisitExpression(tree.Predicate)); 
            }
            else 
            {
                predicateNode = new TreeNode("Predicate");
            }
 
            TreeNode returningNode;
            if (null != tree.Returning) 
            { 
                returningNode = new TreeNode("Returning", _visitor.VisitExpression(tree.Returning));
            } 
            else
            {
                returningNode = new TreeNode("Returning");
            } 

            return this.Print(new TreeNode( 
                "DbUpdateCommandTree", 
                CreateParametersNode(tree),
                targetNode, 
                clausesNode,
                predicateNode,
                returningNode));
        } 

        internal string Print(DbQueryCommandTree tree) 
        { 
            Debug.Assert(tree != null, "Null DbQueryCommandTree");
 
            TreeNode queryNode = new TreeNode("Query");
            if (tree.Query != null)
            {
                PrinterVisitor.AppendTypeSpecifier(queryNode, tree.Query.ResultType); 
                queryNode.Children.Add(_visitor.VisitExpression(tree.Query));
            } 
 
            return this.Print(new TreeNode("DbQueryCommandTree", CreateParametersNode(tree), queryNode));
        } 

        private static TreeNode CreateParametersNode(DbCommandTree tree)
        {
            TreeNode retNode = new TreeNode("Parameters"); 
            foreach (KeyValuePair paramInfo in tree.Parameters)
            { 
                TreeNode paramNode = new TreeNode(paramInfo.Key); 
                PrinterVisitor.AppendTypeSpecifier(paramNode, paramInfo.Value);
                retNode.Children.Add(paramNode); 
            }

            return retNode;
        } 

        private class PrinterVisitor : DbExpressionVisitor 
        { 
            private static Dictionary _opMap = InitializeOpMap();
 
            private static Dictionary InitializeOpMap()
            {
                Dictionary opMap = new Dictionary(12);
 
                // Arithmetic
                opMap[DbExpressionKind.Divide] = "/"; 
                opMap[DbExpressionKind.Modulo] = "%"; 
                opMap[DbExpressionKind.Multiply] = "*";
                opMap[DbExpressionKind.Plus] = "+"; 
                opMap[DbExpressionKind.Minus] = "-";
                opMap[DbExpressionKind.UnaryMinus] = "-";

                // Comparison 
                opMap[DbExpressionKind.Equals] = "=";
                opMap[DbExpressionKind.LessThan] = "<"; 
                opMap[DbExpressionKind.LessThanOrEquals] = "<="; 
                opMap[DbExpressionKind.GreaterThan] = ">";
                opMap[DbExpressionKind.GreaterThanOrEquals] = ">="; 
                opMap[DbExpressionKind.NotEquals] = "<>";

                return opMap;
            } 

            private int _maxStringLength = 80; 
            private bool _infix = true; 

            internal TreeNode VisitExpression(DbExpression expr) 
            {
                return expr.Accept(this);
            }
 
            internal TreeNode VisitExpression(string name, DbExpression expr)
            { 
                return new TreeNode(name, expr.Accept(this)); 
            }
 
            internal TreeNode VisitBinding(string propName, DbExpressionBinding binding)
            {
                return this.VisitWithLabel(propName, binding.VariableName, binding.Expression);
            } 

            internal TreeNode VisitFunction(EdmFunction func, IList args) 
            { 
                TreeNode funcInfo = new TreeNode();
                AppendFullName(funcInfo.Text, func); 

                AppendParameters(funcInfo, func.Parameters.Select(fp => new KeyValuePair(fp.Name, fp.TypeUsage)));
                if (args != null)
                { 
                    AppendArguments(funcInfo, func.Parameters.Select(fp => fp.Name).ToArray(), args);
                } 
 
                return funcInfo;
            } 

            private static TreeNode NodeFromExpression(DbExpression expr)
            {
                return new TreeNode(Enum.GetName(typeof(DbExpressionKind), expr.ExpressionKind)); 
            }
 
            private static void AppendParameters(TreeNode node, IEnumerable> paramInfos) 
            {
                node.Text.Append("("); 
                int pos = 0;
                foreach(KeyValuePair paramInfo in paramInfos)
                {
                    if (pos > 0) 
                    {
                        node.Text.Append(", "); 
                    } 
                    AppendType(node, paramInfo.Value);
                    node.Text.Append(" "); 
                    node.Text.Append(paramInfo.Key);
                    pos++;
                }
                node.Text.Append(")"); 
            }
 
            internal static void AppendTypeSpecifier(TreeNode node, TypeUsage type) 
            {
                node.Text.Append(" : "); 
                AppendType(node, type);
            }

            internal static void AppendType(TreeNode node, TypeUsage type) 
            {
                BuildTypeName(node.Text, type); 
            } 

            private static void BuildTypeName(StringBuilder text, TypeUsage type) 
            {
                RowType rowType = type.EdmType as RowType;
                CollectionType collType = type.EdmType as CollectionType;
                RefType refType = type.EdmType as RefType; 

                if (TypeSemantics.IsPrimitiveType(type)) 
                { 
                    text.Append(type);
                } 
                else if (collType != null)
                {
                    text.Append("Collection{");
                    BuildTypeName(text, collType.TypeUsage); 
                    text.Append("}");
                } 
                else if (refType != null) 
                {
                    text.Append("Ref<"); 
                    AppendFullName(text, refType.ElementType);
                    text.Append(">");
                }
                else if (rowType != null) 
                {
                    text.Append("Record["); 
                    int idx = 0; 
                    foreach (EdmProperty recColumn in rowType.Properties)
                    { 
                        text.Append("'");
                        text.Append(recColumn.Name);
                        text.Append("'");
                        text.Append("="); 
                        BuildTypeName(text, recColumn.TypeUsage);
                        idx++; 
                        if (idx < rowType.Properties.Count) 
                        {
                            text.Append(", "); 
                        }
                    }
                    text.Append("]");
                } 
                else
                { 
                    // Entity, Relationship, Complex 
                    if (!string.IsNullOrEmpty(type.EdmType.NamespaceName))
                    { 
                        text.Append(type.EdmType.NamespaceName);
                        text.Append(".");
                    }
                    text.Append(type.EdmType.Name); 
                }
            } 
 
            private static void AppendFullName(StringBuilder text, EdmType type)
            { 
                if (BuiltInTypeKind.RowType != type.BuiltInTypeKind)
                {
                    if (!string.IsNullOrEmpty(type.NamespaceName))
                    { 
                        text.Append(type.NamespaceName);
                        text.Append("."); 
                    } 
                }
 
                text.Append(type.Name);
            }

            private List VisitParams(IList paramInfo, IList args) 
            {
                List retInfo = new List(); 
                for (int idx = 0; idx < paramInfo.Count; idx++) 
                {
                    TreeNode paramNode = new TreeNode(paramInfo[idx]); 
                    paramNode.Children.Add(this.VisitExpression(args[idx]));
                    retInfo.Add(paramNode);
                }
 
                return retInfo;
            } 
 
            private void AppendArguments(TreeNode node, IList paramNames, IList args)
            { 
                if (paramNames.Count > 0)
                {
                    node.Children.Add(new TreeNode("Arguments", VisitParams(paramNames, args)));
                } 
            }
 
            private TreeNode VisitWithLabel(string label, string name, DbExpression def) 
            {
                TreeNode retInfo = new TreeNode(label); 
                retInfo.Text.Append(" : '");
                retInfo.Text.Append(name);
                retInfo.Text.Append("'");
                retInfo.Children.Add(this.VisitExpression(def)); 

                return retInfo; 
            } 

            private TreeNode VisitBindingList(string propName, IList bindings) 
            {
                List bindingInfos = new List();
                for (int idx = 0; idx < bindings.Count; idx++)
                { 
                    bindingInfos.Add(this.VisitBinding(StringUtil.FormatIndex(propName, idx), bindings[idx]));
                } 
 
                return new TreeNode(propName, bindingInfos);
            } 

            private TreeNode VisitGroupBinding(DbGroupExpressionBinding groupBinding)
            {
                TreeNode inputInfo = this.VisitExpression(groupBinding.Expression); 
                TreeNode retInfo = new TreeNode();
                retInfo.Children.Add(inputInfo); 
                retInfo.Text.AppendFormat(CultureInfo.InvariantCulture, "Input : '{0}', '{1}'", groupBinding.VariableName, groupBinding.GroupVariableName); 
                return retInfo;
            } 

            private TreeNode Visit(string name, params DbExpression[] exprs)
            {
                TreeNode retInfo = new TreeNode(name); 
                foreach (DbExpression expr in exprs)
                { 
                    retInfo.Children.Add(this.VisitExpression(expr)); 
                }
                return retInfo; 
            }

            private TreeNode VisitInfix(DbExpression root, DbExpression left, string name, DbExpression right)
            { 
                if (_infix)
                { 
                    TreeNode nullOp = new TreeNode(""); 
                    nullOp.Children.Add(this.VisitExpression(left));
                    nullOp.Children.Add(new TreeNode(name)); 
                    nullOp.Children.Add(this.VisitExpression(right));

                    return nullOp;
                } 
                else
                { 
                    return Visit(name, left, right); 
                }
            } 

            private TreeNode VisitUnary(DbUnaryExpression expr)
            {
                return VisitUnary(expr, false); 
            }
 
            private TreeNode VisitUnary(DbUnaryExpression expr, bool appendType) 
            {
                TreeNode retInfo = NodeFromExpression(expr); 
                if (appendType)
                {
                    AppendTypeSpecifier(retInfo, expr.ResultType);
                } 
                retInfo.Children.Add(this.VisitExpression(expr.Argument));
                return retInfo; 
            } 

            private TreeNode VisitBinary(DbBinaryExpression expr) 
            {
                TreeNode retInfo = NodeFromExpression(expr);
                retInfo.Children.Add(this.VisitExpression(expr.Left));
                retInfo.Children.Add(this.VisitExpression(expr.Right)); 
                return retInfo;
            } 
 
            #region DbExpressionVisitor Members
 
            public override TreeNode Visit(DbExpression e)
            {
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName));
            } 

            public override TreeNode Visit(DbConstantExpression e) 
            { 
                TreeNode retInfo = new TreeNode();
                string stringVal = e.Value as string; 
                if (stringVal != null)
                {
                    stringVal = stringVal.Replace("\r\n", "\\r\\n");
                    int appendLength = stringVal.Length; 
                    if (_maxStringLength > 0)
                    { 
                        appendLength = Math.Min(stringVal.Length, _maxStringLength); 
                    }
                    retInfo.Text.Append("'"); 
                    retInfo.Text.Append(stringVal, 0, appendLength);
                    if (stringVal.Length > appendLength)
                    {
                        retInfo.Text.Append("..."); 
                    }
                    retInfo.Text.Append("'"); 
                } 
                else
                { 
                    retInfo.Text.Append(e.Value.ToString());
                }

                return retInfo; 
            }
 
            public override TreeNode Visit(DbNullExpression e) 
            {
                return new TreeNode("null"); 
            }

            public override TreeNode Visit(DbVariableReferenceExpression e)
            { 
                TreeNode retInfo = new TreeNode();
                retInfo.Text.AppendFormat("Var({0})", e.VariableName); 
                return retInfo; 
            }
 
            public override TreeNode Visit(DbParameterReferenceExpression e)
            {
                TreeNode retInfo = new TreeNode();
                retInfo.Text.AppendFormat("@{0}", e.ParameterName); 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbFunctionExpression e)
            { 
                TreeNode funcInfo = VisitFunction(e.Function, e.Arguments);
                return funcInfo;
            }
 
            public override TreeNode Visit(DbLambdaExpression expression)
            { 
                TreeNode lambdaInfo = new TreeNode(); 
                lambdaInfo.Text.Append("Lambda");
 
                AppendParameters(lambdaInfo, expression.Lambda.Variables.Select(v => new KeyValuePair(v.VariableName, v.ResultType)));
                AppendArguments(lambdaInfo, expression.Lambda.Variables.Select(v => v.VariableName).ToArray(), expression.Arguments);
                lambdaInfo.Children.Add(this.Visit("Body", expression.Lambda.Body));
 
                return lambdaInfo;
            } 
 
#if METHOD_EXPRESSION
            public override TreeNode Visit(MethodExpression e) 
            {
                TreeNode retInfo = null;
                retInfo = new TreeNode(".");
                AppendType(retInfo, e.Method.DefiningType); 
                retInfo.Text.Append(".");
                retInfo.Text.Append(e.Method.Name); 
                AppendParameters(retInfo, e.Method.Parameters); 
                if (e.Instance != null)
                { 
                    retInfo.Children.Add(this.Visit("Instance", e.Instance));
                }
                AppendArguments(retInfo, e.Method.Parameters, e.Arguments);
 
                return retInfo;
            } 
#endif 

            public override TreeNode Visit(DbPropertyExpression e) 
            {
                TreeNode inst = null;
                if (e.Instance != null)
                { 
                    inst = this.VisitExpression(e.Instance);
                    if (e.Instance.ExpressionKind == DbExpressionKind.VariableReference || 
                        (e.Instance.ExpressionKind == DbExpressionKind.Property && 0 == inst.Children.Count)) 
                    {
                        inst.Text.Append("."); 
                        inst.Text.Append(e.Property.Name);
                        return inst;
                    }
                } 

                TreeNode retInfo = new TreeNode("."); 
                EdmProperty prop = e.Property as EdmProperty; 
                if (prop != null && !(prop.DeclaringType is RowType))
                { 
                    // Entity, Relationship, Complex
                    AppendFullName(retInfo.Text, prop.DeclaringType);
                    retInfo.Text.Append(".");
                } 
                retInfo.Text.Append(e.Property.Name);
 
                if (inst != null) 
                {
                    retInfo.Children.Add(new TreeNode("Instance", inst)); 
                }

                return retInfo;
            } 

            public override TreeNode Visit(DbComparisonExpression e) 
            { 
                return this.VisitInfix(e, e.Left, _opMap[e.ExpressionKind], e.Right);
            } 

            public override TreeNode Visit(DbLikeExpression e)
            {
                return this.Visit("Like", e.Argument, e.Pattern, e.Escape); 
            }
 
            public override TreeNode Visit(DbLimitExpression e) 
            {
                return this.Visit((e.WithTies ? "LimitWithTies" : "Limit"), e.Argument, e.Limit); 
            }

            public override TreeNode Visit(DbIsNullExpression e)
            { 
                return this.VisitUnary(e);
            } 
 
            public override TreeNode Visit(DbArithmeticExpression e)
            { 
                if (DbExpressionKind.UnaryMinus == e.ExpressionKind)
                {
                    return this.Visit(_opMap[e.ExpressionKind], e.Arguments[0]);
                } 
                else
                { 
                    return this.VisitInfix(e, e.Arguments[0], _opMap[e.ExpressionKind], e.Arguments[1]); 
                }
            } 

            public override TreeNode Visit(DbAndExpression e)
            {
                return this.VisitInfix(e, e.Left, "And", e.Right); 
            }
 
            public override TreeNode Visit(DbOrExpression e) 
            {
                return this.VisitInfix(e, e.Left, "Or", e.Right); 
            }

            public override TreeNode Visit(DbNotExpression e)
            { 
                return this.VisitUnary(e);
            } 
 
            public override TreeNode Visit(DbDistinctExpression e)
            { 
                return this.VisitUnary(e);
            }

            public override TreeNode Visit(DbElementExpression e) 
            {
                return this.VisitUnary(e, true); 
            } 

            public override TreeNode Visit(DbIsEmptyExpression e) 
            {
                return this.VisitUnary(e);
            }
 
            public override TreeNode Visit(DbUnionAllExpression e)
            { 
                return this.VisitBinary(e); 
            }
 
            public override TreeNode Visit(DbIntersectExpression e)
            {
                return this.VisitBinary(e);
            } 

            public override TreeNode Visit(DbExceptExpression e) 
            { 
                return this.VisitBinary(e);
            } 

            private TreeNode VisitCastOrTreat(string op, DbUnaryExpression e)
            {
                TreeNode retInfo = null; 
                TreeNode argInfo = this.VisitExpression(e.Argument);
                if (0 == argInfo.Children.Count) 
                { 
                    argInfo.Text.Insert(0, op);
                    argInfo.Text.Insert(op.Length, '('); 
                    argInfo.Text.Append(" As ");
                    AppendType(argInfo, e.ResultType);
                    argInfo.Text.Append(")");
 
                    retInfo = argInfo;
                } 
                else 
                {
                    retInfo = new TreeNode(op); 
                    AppendTypeSpecifier(retInfo, e.ResultType);
                    retInfo.Children.Add(argInfo);
                }
 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbTreatExpression e)
            { 
                return VisitCastOrTreat("Treat", e);
            }

            public override TreeNode Visit(DbCastExpression e) 
            {
                return VisitCastOrTreat("Cast", e); 
            } 

            public override TreeNode Visit(DbIsOfExpression e) 
            {
                TreeNode retInfo = new TreeNode();
                if (DbExpressionKind.IsOfOnly == e.ExpressionKind)
                { 
                    retInfo.Text.Append("IsOfOnly");
                } 
                else 
                {
                    retInfo.Text.Append("IsOf"); 
                }

                AppendTypeSpecifier(retInfo, e.OfType);
                retInfo.Children.Add(this.VisitExpression(e.Argument)); 

                return retInfo; 
            } 

            public override TreeNode Visit(DbOfTypeExpression e) 
            {
                TreeNode retInfo = new TreeNode(e.ExpressionKind == DbExpressionKind.OfTypeOnly ? "OfTypeOnly" : "OfType");
                AppendTypeSpecifier(retInfo, e.OfType);
                retInfo.Children.Add(this.VisitExpression(e.Argument)); 

                return retInfo; 
            } 

            public override TreeNode Visit(DbCaseExpression e) 
            {
                TreeNode retInfo = new TreeNode("Case");
                for (int idx = 0; idx < e.When.Count; idx++)
                { 
                    retInfo.Children.Add(this.Visit("When", e.When[idx]));
                    retInfo.Children.Add(this.Visit("Then", e.Then[idx])); 
                } 

                retInfo.Children.Add(this.Visit("Else", e.Else)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbNewInstanceExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e); 
                AppendTypeSpecifier(retInfo, e.ResultType);
 
                if (BuiltInTypeKind.CollectionType == e.ResultType.EdmType.BuiltInTypeKind)
                {
                    foreach (DbExpression element in e.Arguments)
                    { 
                        retInfo.Children.Add(this.VisitExpression(element));
                    } 
                } 
                else
                { 
                    string description = (BuiltInTypeKind.RowType == e.ResultType.EdmType.BuiltInTypeKind) ? "Column" : "Property";
                    IList properties = TypeHelpers.GetProperties(e.ResultType);
                    for (int idx = 0; idx < properties.Count; idx++)
                    { 
                        retInfo.Children.Add(this.VisitWithLabel(description, properties[idx].Name, e.Arguments[idx]));
                    } 
 
                    if (BuiltInTypeKind.EntityType == e.ResultType.EdmType.BuiltInTypeKind &&
                         e.HasRelatedEntityReferences) 
                    {
                        TreeNode references = new TreeNode("RelatedEntityReferences");
                        foreach (DbRelatedEntityRef relatedRef in e.RelatedEntityReferences)
                        { 
                            TreeNode refNode = CreateNavigationNode(relatedRef.SourceEnd, relatedRef.TargetEnd);
                            refNode.Children.Add(CreateRelationshipNode((RelationshipType)relatedRef.SourceEnd.DeclaringType)); 
                            refNode.Children.Add(VisitExpression(relatedRef.TargetEntityReference)); 

                            references.Children.Add(refNode); 
                        }

                        retInfo.Children.Add(references);
                    } 
                }
                return retInfo; 
            } 

            public override TreeNode Visit(DbRefExpression e) 
            {
                TreeNode retNode = new TreeNode("Ref");
                retNode.Text.Append("<");
                AppendFullName(retNode.Text, TypeHelpers.GetEdmType(e.ResultType).ElementType); 
                retNode.Text.Append(">");
 
                TreeNode setNode = new TreeNode("EntitySet : "); 
                setNode.Text.Append(e.EntitySet.EntityContainer.Name);
                setNode.Text.Append("."); 
                setNode.Text.Append(e.EntitySet.Name);

                retNode.Children.Add(setNode);
                retNode.Children.Add(this.Visit("Keys", e.Argument)); 

                return retNode; 
            } 

            private TreeNode CreateRelationshipNode(RelationshipType relType) 
            {
                TreeNode rel = new TreeNode("Relationship");
                rel.Text.Append(" : ");
                AppendFullName(rel.Text, relType); 
                return rel;
            } 
 
            private TreeNode CreateNavigationNode(RelationshipEndMember fromEnd, RelationshipEndMember toEnd)
            { 
                TreeNode nav = new TreeNode();
                nav.Text.Append("Navigation : ");
                nav.Text.Append(fromEnd.Name);
                nav.Text.Append(" -> "); 
                nav.Text.Append(toEnd.Name);
                return nav; 
            } 

            public override TreeNode Visit(DbRelationshipNavigationExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(CreateRelationshipNode(e.Relationship));
                retInfo.Children.Add(CreateNavigationNode(e.NavigateFrom, e.NavigateTo)); 
                retInfo.Children.Add(this.Visit("Source", e.NavigationSource));
 
                return retInfo; 
            }
 
            public override TreeNode Visit(DbDerefExpression e)
            {
                return this.VisitUnary(e);
            } 

            public override TreeNode Visit(DbRefKeyExpression e) 
            { 
                return this.VisitUnary(e, true);
            } 

            public override TreeNode Visit(DbEntityRefExpression e)
            {
                return this.VisitUnary(e, true); 
            }
 
            public override TreeNode Visit(DbScanExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Text.Append(" : ");
                retInfo.Text.Append(e.Target.EntityContainer.Name);
                retInfo.Text.Append(".");
                retInfo.Text.Append(e.Target.Name); 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbFilterExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Predicate", e.Predicate));
                return retInfo; 
            }
 
            public override TreeNode Visit(DbProjectExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Projection", e.Projection));
                return retInfo;
            } 

            public override TreeNode Visit(DbCrossJoinExpression e) 
            { 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitBindingList("Inputs", e.Inputs)); 
                return retInfo;
            }

            public override TreeNode Visit(DbJoinExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Left", e.Left)); 
                retInfo.Children.Add(this.VisitBinding("Right", e.Right));
                retInfo.Children.Add(this.Visit("JoinCondition", e.JoinCondition)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbApplyExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitBinding("Apply", e.Apply)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbGroupByExpression e)
            { 
                List keys = new List(); 
                List aggs = new List();
 
                RowType outputType = TypeHelpers.GetEdmType(TypeHelpers.GetEdmType(e.ResultType).TypeUsage);
                int keyIdx = 0;
                for (int idx = 0; idx < e.Keys.Count; idx++)
                { 
                    keys.Add(this.VisitWithLabel("Key", outputType.Properties[idx].Name, e.Keys[keyIdx]));
                    keyIdx++; 
                } 

                int aggIdx = 0; 
                for (int idx = e.Keys.Count; idx < outputType.Properties.Count; idx++)
                {
                    TreeNode aggInfo = new TreeNode("Aggregate : '");
                    aggInfo.Text.Append(outputType.Properties[idx].Name); 
                    aggInfo.Text.Append("'");
 
                    DbFunctionAggregate funcAgg = e.Aggregates[aggIdx] as DbFunctionAggregate; 
                    if (funcAgg != null)
                    { 
                        TreeNode funcInfo = this.VisitFunction(funcAgg.Function, funcAgg.Arguments);
                        if (funcAgg.Distinct)
                        {
                            funcInfo = new TreeNode("Distinct", funcInfo); 
                        }
                        aggInfo.Children.Add(funcInfo); 
                    } 
                    else
                    { 
                        DbGroupAggregate groupAgg = e.Aggregates[aggIdx] as DbGroupAggregate;
                        Debug.Assert(groupAgg != null, "Invalid DbAggregate");
                        aggInfo.Children.Add(this.Visit("GroupAggregate", groupAgg.Arguments[0]));
                    } 

                    aggs.Add(aggInfo); 
                    aggIdx++; 
                }
 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitGroupBinding(e.Input));
                if (keys.Count > 0)
                { 
                    retInfo.Children.Add(new TreeNode("Keys", keys));
                } 
 
                if (aggs.Count > 0)
                { 
                    retInfo.Children.Add(new TreeNode("Aggregates", aggs));
                }

                return retInfo; 
            }
 
            private TreeNode VisitSortOrder(IList sortOrder) 
            {
                TreeNode keyInfo = new TreeNode("SortOrder"); 
                foreach (DbSortClause clause in sortOrder)
                {
                    TreeNode key = this.Visit((clause.Ascending ? "Asc" : "Desc"), clause.Expression);
                    if (!string.IsNullOrEmpty(clause.Collation)) 
                    {
                        key.Text.Append(" : "); 
                        key.Text.Append(clause.Collation); 
                    }
 
                    keyInfo.Children.Add(key);
                }

                return keyInfo; 
            }
 
            public override TreeNode Visit(DbSkipExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitSortOrder(e.SortOrder));
                retInfo.Children.Add(this.Visit("Count", e.Count));
                return retInfo; 
            }
 
            public override TreeNode Visit(DbSortExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitSortOrder(e.SortOrder));

                return retInfo; 
            }
 
            public override TreeNode Visit(DbQuantifierExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Predicate", e.Predicate));
                return retInfo;
            } 
            #endregion
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq; 
using System.Reflection;
using System.Text; 
 
using System.Data.Common;
using System.Data.Common.Utils; 
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;

namespace System.Data.Common.CommandTrees.Internal 
{
    ///  
    /// Prints a command tree 
    /// 
    internal class ExpressionPrinter : TreePrinter 
    {
        private PrinterVisitor _visitor = new PrinterVisitor();

        internal ExpressionPrinter() 
            : base() {}
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 
        internal string Print(DbExpression expr)
        { 
            Debug.Assert(expr != null, "Null DbExpression");
            return this.Print(_visitor.VisitExpression(expr));
        }
 
        internal string Print(DbDeleteCommandTree tree)
        { 
            // Predicate should not be null since DbDeleteCommandTree initializes it to DbConstantExpression(true) 
            Debug.Assert(tree != null && tree.Predicate != null, "Invalid DbDeleteCommandTree");
 
            TreeNode targetNode;
            if (tree.Target != null)
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            }
            else 
            { 
                targetNode = new TreeNode("Target");
            } 

            TreeNode predicateNode;
            if (tree.Predicate != null)
            { 
                predicateNode = _visitor.VisitExpression("Predicate", tree.Predicate);
            } 
            else 
            {
                predicateNode = new TreeNode("Predicate"); 
            }

            return this.Print(new TreeNode(
                    "DbDeleteCommandTree", 
                    CreateParametersNode(tree),
                    targetNode, 
                    predicateNode)); 
        }
 
        internal string Print(DbFunctionCommandTree tree)
        {
            Debug.Assert(tree != null, "Null DbFunctionCommandTree");
 
            TreeNode funcNode = new TreeNode("EdmFunction");
            if (tree.EdmFunction != null) 
            { 
                funcNode.Children.Add(_visitor.VisitFunction(tree.EdmFunction, null));
            } 

            TreeNode typeNode = new TreeNode("ResultType");
            if (tree.ResultType != null)
            { 
                PrinterVisitor.AppendTypeSpecifier(typeNode, tree.ResultType);
            } 
 
            return this.Print(new TreeNode("DbFunctionCommandTree", CreateParametersNode(tree), funcNode, typeNode));
        } 

        internal string Print(DbInsertCommandTree tree)
        {
            Debug.Assert(tree != null, "Null DbInsertCommandTree"); 

            TreeNode targetNode = null; 
            if (tree.Target != null) 
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            }
            else
            {
                targetNode = new TreeNode("Target"); 
            }
 
            TreeNode clausesNode = new TreeNode("SetClauses"); 
            foreach (DbModificationClause clause in tree.SetClauses)
            { 
                if (clause != null)
                {
                    clausesNode.Children.Add(clause.Print(_visitor));
                } 
            }
 
            TreeNode returningNode = null; 
            if (null != tree.Returning)
            { 
                returningNode = new TreeNode("Returning", _visitor.VisitExpression(tree.Returning));
            }
            else
            { 
                returningNode = new TreeNode("Returning");
            } 
 
            return this.Print(new TreeNode(
                "DbInsertCommandTree", 
                CreateParametersNode(tree),
                targetNode,
                clausesNode,
                returningNode)); 
        }
 
        internal string Print(DbUpdateCommandTree tree) 
        {
            // Predicate should not be null since DbUpdateCommandTree initializes it to DbConstantExpression(true) 
            Debug.Assert(tree != null && tree.Predicate != null, "Invalid DbUpdateCommandTree");

            TreeNode targetNode = null;
            if (tree.Target != null) 
            {
                targetNode = _visitor.VisitBinding("Target", tree.Target); 
            } 
            else
            { 
                targetNode = new TreeNode("Target");
            }

            TreeNode clausesNode = new TreeNode("SetClauses"); 
            foreach (DbModificationClause clause in tree.SetClauses)
            { 
                if (clause != null) 
                {
                    clausesNode.Children.Add(clause.Print(_visitor)); 
                }
            }

            TreeNode predicateNode; 
            if (null != tree.Predicate)
            { 
                predicateNode = new TreeNode("Predicate", _visitor.VisitExpression(tree.Predicate)); 
            }
            else 
            {
                predicateNode = new TreeNode("Predicate");
            }
 
            TreeNode returningNode;
            if (null != tree.Returning) 
            { 
                returningNode = new TreeNode("Returning", _visitor.VisitExpression(tree.Returning));
            } 
            else
            {
                returningNode = new TreeNode("Returning");
            } 

            return this.Print(new TreeNode( 
                "DbUpdateCommandTree", 
                CreateParametersNode(tree),
                targetNode, 
                clausesNode,
                predicateNode,
                returningNode));
        } 

        internal string Print(DbQueryCommandTree tree) 
        { 
            Debug.Assert(tree != null, "Null DbQueryCommandTree");
 
            TreeNode queryNode = new TreeNode("Query");
            if (tree.Query != null)
            {
                PrinterVisitor.AppendTypeSpecifier(queryNode, tree.Query.ResultType); 
                queryNode.Children.Add(_visitor.VisitExpression(tree.Query));
            } 
 
            return this.Print(new TreeNode("DbQueryCommandTree", CreateParametersNode(tree), queryNode));
        } 

        private static TreeNode CreateParametersNode(DbCommandTree tree)
        {
            TreeNode retNode = new TreeNode("Parameters"); 
            foreach (KeyValuePair paramInfo in tree.Parameters)
            { 
                TreeNode paramNode = new TreeNode(paramInfo.Key); 
                PrinterVisitor.AppendTypeSpecifier(paramNode, paramInfo.Value);
                retNode.Children.Add(paramNode); 
            }

            return retNode;
        } 

        private class PrinterVisitor : DbExpressionVisitor 
        { 
            private static Dictionary _opMap = InitializeOpMap();
 
            private static Dictionary InitializeOpMap()
            {
                Dictionary opMap = new Dictionary(12);
 
                // Arithmetic
                opMap[DbExpressionKind.Divide] = "/"; 
                opMap[DbExpressionKind.Modulo] = "%"; 
                opMap[DbExpressionKind.Multiply] = "*";
                opMap[DbExpressionKind.Plus] = "+"; 
                opMap[DbExpressionKind.Minus] = "-";
                opMap[DbExpressionKind.UnaryMinus] = "-";

                // Comparison 
                opMap[DbExpressionKind.Equals] = "=";
                opMap[DbExpressionKind.LessThan] = "<"; 
                opMap[DbExpressionKind.LessThanOrEquals] = "<="; 
                opMap[DbExpressionKind.GreaterThan] = ">";
                opMap[DbExpressionKind.GreaterThanOrEquals] = ">="; 
                opMap[DbExpressionKind.NotEquals] = "<>";

                return opMap;
            } 

            private int _maxStringLength = 80; 
            private bool _infix = true; 

            internal TreeNode VisitExpression(DbExpression expr) 
            {
                return expr.Accept(this);
            }
 
            internal TreeNode VisitExpression(string name, DbExpression expr)
            { 
                return new TreeNode(name, expr.Accept(this)); 
            }
 
            internal TreeNode VisitBinding(string propName, DbExpressionBinding binding)
            {
                return this.VisitWithLabel(propName, binding.VariableName, binding.Expression);
            } 

            internal TreeNode VisitFunction(EdmFunction func, IList args) 
            { 
                TreeNode funcInfo = new TreeNode();
                AppendFullName(funcInfo.Text, func); 

                AppendParameters(funcInfo, func.Parameters.Select(fp => new KeyValuePair(fp.Name, fp.TypeUsage)));
                if (args != null)
                { 
                    AppendArguments(funcInfo, func.Parameters.Select(fp => fp.Name).ToArray(), args);
                } 
 
                return funcInfo;
            } 

            private static TreeNode NodeFromExpression(DbExpression expr)
            {
                return new TreeNode(Enum.GetName(typeof(DbExpressionKind), expr.ExpressionKind)); 
            }
 
            private static void AppendParameters(TreeNode node, IEnumerable> paramInfos) 
            {
                node.Text.Append("("); 
                int pos = 0;
                foreach(KeyValuePair paramInfo in paramInfos)
                {
                    if (pos > 0) 
                    {
                        node.Text.Append(", "); 
                    } 
                    AppendType(node, paramInfo.Value);
                    node.Text.Append(" "); 
                    node.Text.Append(paramInfo.Key);
                    pos++;
                }
                node.Text.Append(")"); 
            }
 
            internal static void AppendTypeSpecifier(TreeNode node, TypeUsage type) 
            {
                node.Text.Append(" : "); 
                AppendType(node, type);
            }

            internal static void AppendType(TreeNode node, TypeUsage type) 
            {
                BuildTypeName(node.Text, type); 
            } 

            private static void BuildTypeName(StringBuilder text, TypeUsage type) 
            {
                RowType rowType = type.EdmType as RowType;
                CollectionType collType = type.EdmType as CollectionType;
                RefType refType = type.EdmType as RefType; 

                if (TypeSemantics.IsPrimitiveType(type)) 
                { 
                    text.Append(type);
                } 
                else if (collType != null)
                {
                    text.Append("Collection{");
                    BuildTypeName(text, collType.TypeUsage); 
                    text.Append("}");
                } 
                else if (refType != null) 
                {
                    text.Append("Ref<"); 
                    AppendFullName(text, refType.ElementType);
                    text.Append(">");
                }
                else if (rowType != null) 
                {
                    text.Append("Record["); 
                    int idx = 0; 
                    foreach (EdmProperty recColumn in rowType.Properties)
                    { 
                        text.Append("'");
                        text.Append(recColumn.Name);
                        text.Append("'");
                        text.Append("="); 
                        BuildTypeName(text, recColumn.TypeUsage);
                        idx++; 
                        if (idx < rowType.Properties.Count) 
                        {
                            text.Append(", "); 
                        }
                    }
                    text.Append("]");
                } 
                else
                { 
                    // Entity, Relationship, Complex 
                    if (!string.IsNullOrEmpty(type.EdmType.NamespaceName))
                    { 
                        text.Append(type.EdmType.NamespaceName);
                        text.Append(".");
                    }
                    text.Append(type.EdmType.Name); 
                }
            } 
 
            private static void AppendFullName(StringBuilder text, EdmType type)
            { 
                if (BuiltInTypeKind.RowType != type.BuiltInTypeKind)
                {
                    if (!string.IsNullOrEmpty(type.NamespaceName))
                    { 
                        text.Append(type.NamespaceName);
                        text.Append("."); 
                    } 
                }
 
                text.Append(type.Name);
            }

            private List VisitParams(IList paramInfo, IList args) 
            {
                List retInfo = new List(); 
                for (int idx = 0; idx < paramInfo.Count; idx++) 
                {
                    TreeNode paramNode = new TreeNode(paramInfo[idx]); 
                    paramNode.Children.Add(this.VisitExpression(args[idx]));
                    retInfo.Add(paramNode);
                }
 
                return retInfo;
            } 
 
            private void AppendArguments(TreeNode node, IList paramNames, IList args)
            { 
                if (paramNames.Count > 0)
                {
                    node.Children.Add(new TreeNode("Arguments", VisitParams(paramNames, args)));
                } 
            }
 
            private TreeNode VisitWithLabel(string label, string name, DbExpression def) 
            {
                TreeNode retInfo = new TreeNode(label); 
                retInfo.Text.Append(" : '");
                retInfo.Text.Append(name);
                retInfo.Text.Append("'");
                retInfo.Children.Add(this.VisitExpression(def)); 

                return retInfo; 
            } 

            private TreeNode VisitBindingList(string propName, IList bindings) 
            {
                List bindingInfos = new List();
                for (int idx = 0; idx < bindings.Count; idx++)
                { 
                    bindingInfos.Add(this.VisitBinding(StringUtil.FormatIndex(propName, idx), bindings[idx]));
                } 
 
                return new TreeNode(propName, bindingInfos);
            } 

            private TreeNode VisitGroupBinding(DbGroupExpressionBinding groupBinding)
            {
                TreeNode inputInfo = this.VisitExpression(groupBinding.Expression); 
                TreeNode retInfo = new TreeNode();
                retInfo.Children.Add(inputInfo); 
                retInfo.Text.AppendFormat(CultureInfo.InvariantCulture, "Input : '{0}', '{1}'", groupBinding.VariableName, groupBinding.GroupVariableName); 
                return retInfo;
            } 

            private TreeNode Visit(string name, params DbExpression[] exprs)
            {
                TreeNode retInfo = new TreeNode(name); 
                foreach (DbExpression expr in exprs)
                { 
                    retInfo.Children.Add(this.VisitExpression(expr)); 
                }
                return retInfo; 
            }

            private TreeNode VisitInfix(DbExpression root, DbExpression left, string name, DbExpression right)
            { 
                if (_infix)
                { 
                    TreeNode nullOp = new TreeNode(""); 
                    nullOp.Children.Add(this.VisitExpression(left));
                    nullOp.Children.Add(new TreeNode(name)); 
                    nullOp.Children.Add(this.VisitExpression(right));

                    return nullOp;
                } 
                else
                { 
                    return Visit(name, left, right); 
                }
            } 

            private TreeNode VisitUnary(DbUnaryExpression expr)
            {
                return VisitUnary(expr, false); 
            }
 
            private TreeNode VisitUnary(DbUnaryExpression expr, bool appendType) 
            {
                TreeNode retInfo = NodeFromExpression(expr); 
                if (appendType)
                {
                    AppendTypeSpecifier(retInfo, expr.ResultType);
                } 
                retInfo.Children.Add(this.VisitExpression(expr.Argument));
                return retInfo; 
            } 

            private TreeNode VisitBinary(DbBinaryExpression expr) 
            {
                TreeNode retInfo = NodeFromExpression(expr);
                retInfo.Children.Add(this.VisitExpression(expr.Left));
                retInfo.Children.Add(this.VisitExpression(expr.Right)); 
                return retInfo;
            } 
 
            #region DbExpressionVisitor Members
 
            public override TreeNode Visit(DbExpression e)
            {
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName));
            } 

            public override TreeNode Visit(DbConstantExpression e) 
            { 
                TreeNode retInfo = new TreeNode();
                string stringVal = e.Value as string; 
                if (stringVal != null)
                {
                    stringVal = stringVal.Replace("\r\n", "\\r\\n");
                    int appendLength = stringVal.Length; 
                    if (_maxStringLength > 0)
                    { 
                        appendLength = Math.Min(stringVal.Length, _maxStringLength); 
                    }
                    retInfo.Text.Append("'"); 
                    retInfo.Text.Append(stringVal, 0, appendLength);
                    if (stringVal.Length > appendLength)
                    {
                        retInfo.Text.Append("..."); 
                    }
                    retInfo.Text.Append("'"); 
                } 
                else
                { 
                    retInfo.Text.Append(e.Value.ToString());
                }

                return retInfo; 
            }
 
            public override TreeNode Visit(DbNullExpression e) 
            {
                return new TreeNode("null"); 
            }

            public override TreeNode Visit(DbVariableReferenceExpression e)
            { 
                TreeNode retInfo = new TreeNode();
                retInfo.Text.AppendFormat("Var({0})", e.VariableName); 
                return retInfo; 
            }
 
            public override TreeNode Visit(DbParameterReferenceExpression e)
            {
                TreeNode retInfo = new TreeNode();
                retInfo.Text.AppendFormat("@{0}", e.ParameterName); 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbFunctionExpression e)
            { 
                TreeNode funcInfo = VisitFunction(e.Function, e.Arguments);
                return funcInfo;
            }
 
            public override TreeNode Visit(DbLambdaExpression expression)
            { 
                TreeNode lambdaInfo = new TreeNode(); 
                lambdaInfo.Text.Append("Lambda");
 
                AppendParameters(lambdaInfo, expression.Lambda.Variables.Select(v => new KeyValuePair(v.VariableName, v.ResultType)));
                AppendArguments(lambdaInfo, expression.Lambda.Variables.Select(v => v.VariableName).ToArray(), expression.Arguments);
                lambdaInfo.Children.Add(this.Visit("Body", expression.Lambda.Body));
 
                return lambdaInfo;
            } 
 
#if METHOD_EXPRESSION
            public override TreeNode Visit(MethodExpression e) 
            {
                TreeNode retInfo = null;
                retInfo = new TreeNode(".");
                AppendType(retInfo, e.Method.DefiningType); 
                retInfo.Text.Append(".");
                retInfo.Text.Append(e.Method.Name); 
                AppendParameters(retInfo, e.Method.Parameters); 
                if (e.Instance != null)
                { 
                    retInfo.Children.Add(this.Visit("Instance", e.Instance));
                }
                AppendArguments(retInfo, e.Method.Parameters, e.Arguments);
 
                return retInfo;
            } 
#endif 

            public override TreeNode Visit(DbPropertyExpression e) 
            {
                TreeNode inst = null;
                if (e.Instance != null)
                { 
                    inst = this.VisitExpression(e.Instance);
                    if (e.Instance.ExpressionKind == DbExpressionKind.VariableReference || 
                        (e.Instance.ExpressionKind == DbExpressionKind.Property && 0 == inst.Children.Count)) 
                    {
                        inst.Text.Append("."); 
                        inst.Text.Append(e.Property.Name);
                        return inst;
                    }
                } 

                TreeNode retInfo = new TreeNode("."); 
                EdmProperty prop = e.Property as EdmProperty; 
                if (prop != null && !(prop.DeclaringType is RowType))
                { 
                    // Entity, Relationship, Complex
                    AppendFullName(retInfo.Text, prop.DeclaringType);
                    retInfo.Text.Append(".");
                } 
                retInfo.Text.Append(e.Property.Name);
 
                if (inst != null) 
                {
                    retInfo.Children.Add(new TreeNode("Instance", inst)); 
                }

                return retInfo;
            } 

            public override TreeNode Visit(DbComparisonExpression e) 
            { 
                return this.VisitInfix(e, e.Left, _opMap[e.ExpressionKind], e.Right);
            } 

            public override TreeNode Visit(DbLikeExpression e)
            {
                return this.Visit("Like", e.Argument, e.Pattern, e.Escape); 
            }
 
            public override TreeNode Visit(DbLimitExpression e) 
            {
                return this.Visit((e.WithTies ? "LimitWithTies" : "Limit"), e.Argument, e.Limit); 
            }

            public override TreeNode Visit(DbIsNullExpression e)
            { 
                return this.VisitUnary(e);
            } 
 
            public override TreeNode Visit(DbArithmeticExpression e)
            { 
                if (DbExpressionKind.UnaryMinus == e.ExpressionKind)
                {
                    return this.Visit(_opMap[e.ExpressionKind], e.Arguments[0]);
                } 
                else
                { 
                    return this.VisitInfix(e, e.Arguments[0], _opMap[e.ExpressionKind], e.Arguments[1]); 
                }
            } 

            public override TreeNode Visit(DbAndExpression e)
            {
                return this.VisitInfix(e, e.Left, "And", e.Right); 
            }
 
            public override TreeNode Visit(DbOrExpression e) 
            {
                return this.VisitInfix(e, e.Left, "Or", e.Right); 
            }

            public override TreeNode Visit(DbNotExpression e)
            { 
                return this.VisitUnary(e);
            } 
 
            public override TreeNode Visit(DbDistinctExpression e)
            { 
                return this.VisitUnary(e);
            }

            public override TreeNode Visit(DbElementExpression e) 
            {
                return this.VisitUnary(e, true); 
            } 

            public override TreeNode Visit(DbIsEmptyExpression e) 
            {
                return this.VisitUnary(e);
            }
 
            public override TreeNode Visit(DbUnionAllExpression e)
            { 
                return this.VisitBinary(e); 
            }
 
            public override TreeNode Visit(DbIntersectExpression e)
            {
                return this.VisitBinary(e);
            } 

            public override TreeNode Visit(DbExceptExpression e) 
            { 
                return this.VisitBinary(e);
            } 

            private TreeNode VisitCastOrTreat(string op, DbUnaryExpression e)
            {
                TreeNode retInfo = null; 
                TreeNode argInfo = this.VisitExpression(e.Argument);
                if (0 == argInfo.Children.Count) 
                { 
                    argInfo.Text.Insert(0, op);
                    argInfo.Text.Insert(op.Length, '('); 
                    argInfo.Text.Append(" As ");
                    AppendType(argInfo, e.ResultType);
                    argInfo.Text.Append(")");
 
                    retInfo = argInfo;
                } 
                else 
                {
                    retInfo = new TreeNode(op); 
                    AppendTypeSpecifier(retInfo, e.ResultType);
                    retInfo.Children.Add(argInfo);
                }
 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbTreatExpression e)
            { 
                return VisitCastOrTreat("Treat", e);
            }

            public override TreeNode Visit(DbCastExpression e) 
            {
                return VisitCastOrTreat("Cast", e); 
            } 

            public override TreeNode Visit(DbIsOfExpression e) 
            {
                TreeNode retInfo = new TreeNode();
                if (DbExpressionKind.IsOfOnly == e.ExpressionKind)
                { 
                    retInfo.Text.Append("IsOfOnly");
                } 
                else 
                {
                    retInfo.Text.Append("IsOf"); 
                }

                AppendTypeSpecifier(retInfo, e.OfType);
                retInfo.Children.Add(this.VisitExpression(e.Argument)); 

                return retInfo; 
            } 

            public override TreeNode Visit(DbOfTypeExpression e) 
            {
                TreeNode retInfo = new TreeNode(e.ExpressionKind == DbExpressionKind.OfTypeOnly ? "OfTypeOnly" : "OfType");
                AppendTypeSpecifier(retInfo, e.OfType);
                retInfo.Children.Add(this.VisitExpression(e.Argument)); 

                return retInfo; 
            } 

            public override TreeNode Visit(DbCaseExpression e) 
            {
                TreeNode retInfo = new TreeNode("Case");
                for (int idx = 0; idx < e.When.Count; idx++)
                { 
                    retInfo.Children.Add(this.Visit("When", e.When[idx]));
                    retInfo.Children.Add(this.Visit("Then", e.Then[idx])); 
                } 

                retInfo.Children.Add(this.Visit("Else", e.Else)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbNewInstanceExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e); 
                AppendTypeSpecifier(retInfo, e.ResultType);
 
                if (BuiltInTypeKind.CollectionType == e.ResultType.EdmType.BuiltInTypeKind)
                {
                    foreach (DbExpression element in e.Arguments)
                    { 
                        retInfo.Children.Add(this.VisitExpression(element));
                    } 
                } 
                else
                { 
                    string description = (BuiltInTypeKind.RowType == e.ResultType.EdmType.BuiltInTypeKind) ? "Column" : "Property";
                    IList properties = TypeHelpers.GetProperties(e.ResultType);
                    for (int idx = 0; idx < properties.Count; idx++)
                    { 
                        retInfo.Children.Add(this.VisitWithLabel(description, properties[idx].Name, e.Arguments[idx]));
                    } 
 
                    if (BuiltInTypeKind.EntityType == e.ResultType.EdmType.BuiltInTypeKind &&
                         e.HasRelatedEntityReferences) 
                    {
                        TreeNode references = new TreeNode("RelatedEntityReferences");
                        foreach (DbRelatedEntityRef relatedRef in e.RelatedEntityReferences)
                        { 
                            TreeNode refNode = CreateNavigationNode(relatedRef.SourceEnd, relatedRef.TargetEnd);
                            refNode.Children.Add(CreateRelationshipNode((RelationshipType)relatedRef.SourceEnd.DeclaringType)); 
                            refNode.Children.Add(VisitExpression(relatedRef.TargetEntityReference)); 

                            references.Children.Add(refNode); 
                        }

                        retInfo.Children.Add(references);
                    } 
                }
                return retInfo; 
            } 

            public override TreeNode Visit(DbRefExpression e) 
            {
                TreeNode retNode = new TreeNode("Ref");
                retNode.Text.Append("<");
                AppendFullName(retNode.Text, TypeHelpers.GetEdmType(e.ResultType).ElementType); 
                retNode.Text.Append(">");
 
                TreeNode setNode = new TreeNode("EntitySet : "); 
                setNode.Text.Append(e.EntitySet.EntityContainer.Name);
                setNode.Text.Append("."); 
                setNode.Text.Append(e.EntitySet.Name);

                retNode.Children.Add(setNode);
                retNode.Children.Add(this.Visit("Keys", e.Argument)); 

                return retNode; 
            } 

            private TreeNode CreateRelationshipNode(RelationshipType relType) 
            {
                TreeNode rel = new TreeNode("Relationship");
                rel.Text.Append(" : ");
                AppendFullName(rel.Text, relType); 
                return rel;
            } 
 
            private TreeNode CreateNavigationNode(RelationshipEndMember fromEnd, RelationshipEndMember toEnd)
            { 
                TreeNode nav = new TreeNode();
                nav.Text.Append("Navigation : ");
                nav.Text.Append(fromEnd.Name);
                nav.Text.Append(" -> "); 
                nav.Text.Append(toEnd.Name);
                return nav; 
            } 

            public override TreeNode Visit(DbRelationshipNavigationExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(CreateRelationshipNode(e.Relationship));
                retInfo.Children.Add(CreateNavigationNode(e.NavigateFrom, e.NavigateTo)); 
                retInfo.Children.Add(this.Visit("Source", e.NavigationSource));
 
                return retInfo; 
            }
 
            public override TreeNode Visit(DbDerefExpression e)
            {
                return this.VisitUnary(e);
            } 

            public override TreeNode Visit(DbRefKeyExpression e) 
            { 
                return this.VisitUnary(e, true);
            } 

            public override TreeNode Visit(DbEntityRefExpression e)
            {
                return this.VisitUnary(e, true); 
            }
 
            public override TreeNode Visit(DbScanExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Text.Append(" : ");
                retInfo.Text.Append(e.Target.EntityContainer.Name);
                retInfo.Text.Append(".");
                retInfo.Text.Append(e.Target.Name); 
                return retInfo;
            } 
 
            public override TreeNode Visit(DbFilterExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Predicate", e.Predicate));
                return retInfo; 
            }
 
            public override TreeNode Visit(DbProjectExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Projection", e.Projection));
                return retInfo;
            } 

            public override TreeNode Visit(DbCrossJoinExpression e) 
            { 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitBindingList("Inputs", e.Inputs)); 
                return retInfo;
            }

            public override TreeNode Visit(DbJoinExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Left", e.Left)); 
                retInfo.Children.Add(this.VisitBinding("Right", e.Right));
                retInfo.Children.Add(this.Visit("JoinCondition", e.JoinCondition)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbApplyExpression e)
            { 
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitBinding("Apply", e.Apply)); 

                return retInfo;
            }
 
            public override TreeNode Visit(DbGroupByExpression e)
            { 
                List keys = new List(); 
                List aggs = new List();
 
                RowType outputType = TypeHelpers.GetEdmType(TypeHelpers.GetEdmType(e.ResultType).TypeUsage);
                int keyIdx = 0;
                for (int idx = 0; idx < e.Keys.Count; idx++)
                { 
                    keys.Add(this.VisitWithLabel("Key", outputType.Properties[idx].Name, e.Keys[keyIdx]));
                    keyIdx++; 
                } 

                int aggIdx = 0; 
                for (int idx = e.Keys.Count; idx < outputType.Properties.Count; idx++)
                {
                    TreeNode aggInfo = new TreeNode("Aggregate : '");
                    aggInfo.Text.Append(outputType.Properties[idx].Name); 
                    aggInfo.Text.Append("'");
 
                    DbFunctionAggregate funcAgg = e.Aggregates[aggIdx] as DbFunctionAggregate; 
                    if (funcAgg != null)
                    { 
                        TreeNode funcInfo = this.VisitFunction(funcAgg.Function, funcAgg.Arguments);
                        if (funcAgg.Distinct)
                        {
                            funcInfo = new TreeNode("Distinct", funcInfo); 
                        }
                        aggInfo.Children.Add(funcInfo); 
                    } 
                    else
                    { 
                        DbGroupAggregate groupAgg = e.Aggregates[aggIdx] as DbGroupAggregate;
                        Debug.Assert(groupAgg != null, "Invalid DbAggregate");
                        aggInfo.Children.Add(this.Visit("GroupAggregate", groupAgg.Arguments[0]));
                    } 

                    aggs.Add(aggInfo); 
                    aggIdx++; 
                }
 
                TreeNode retInfo = NodeFromExpression(e);
                retInfo.Children.Add(this.VisitGroupBinding(e.Input));
                if (keys.Count > 0)
                { 
                    retInfo.Children.Add(new TreeNode("Keys", keys));
                } 
 
                if (aggs.Count > 0)
                { 
                    retInfo.Children.Add(new TreeNode("Aggregates", aggs));
                }

                return retInfo; 
            }
 
            private TreeNode VisitSortOrder(IList sortOrder) 
            {
                TreeNode keyInfo = new TreeNode("SortOrder"); 
                foreach (DbSortClause clause in sortOrder)
                {
                    TreeNode key = this.Visit((clause.Ascending ? "Asc" : "Desc"), clause.Expression);
                    if (!string.IsNullOrEmpty(clause.Collation)) 
                    {
                        key.Text.Append(" : "); 
                        key.Text.Append(clause.Collation); 
                    }
 
                    keyInfo.Children.Add(key);
                }

                return keyInfo; 
            }
 
            public override TreeNode Visit(DbSkipExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitSortOrder(e.SortOrder));
                retInfo.Children.Add(this.Visit("Count", e.Count));
                return retInfo; 
            }
 
            public override TreeNode Visit(DbSortExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.VisitSortOrder(e.SortOrder));

                return retInfo; 
            }
 
            public override TreeNode Visit(DbQuantifierExpression e) 
            {
                TreeNode retInfo = NodeFromExpression(e); 
                retInfo.Children.Add(this.VisitBinding("Input", e.Input));
                retInfo.Children.Add(this.Visit("Predicate", e.Predicate));
                return retInfo;
            } 
            #endregion
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK