File: DataBindingExpressionBuilder.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (153 lines) | stat: -rw-r--r-- 9,219 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//------------------------------------------------------------------------------
// <copyright file="DataBindingExpressionBuilder.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Web.Compilation {
    using System;
    using System.Security.Permissions;
    using System.CodeDom;
    using System.Diagnostics;
    using System.Reflection;
    using System.Web.UI;


    internal class DataBindingExpressionBuilder : ExpressionBuilder {
        private static EventInfo eventInfo;
        private const string EvalMethodName = "Eval";
        private const string GetDataItemMethodName = "GetDataItem";

        internal static EventInfo Event {
            get {
                if (eventInfo == null) {
                    eventInfo = typeof(Control).GetEvent("DataBinding");
                }

                return eventInfo;
            }
        }

        internal static void BuildEvalExpression(string field, string formatString, string propertyName,
            Type propertyType, ControlBuilder controlBuilder, CodeStatementCollection methodStatements, CodeStatementCollection statements, CodeLinePragma linePragma, bool isEncoded, ref bool hasTempObject) {

            // Altogether, this function will create a statement that looks like this:
            // if (this.Page.GetDataItem() != null) {
            //     target.{{propName}} = ({{propType}}) this.Eval(fieldName, formatString);
            // }

            //     this.Eval(fieldName, formatString)
            CodeMethodInvokeExpression evalExpr = new CodeMethodInvokeExpression();
            evalExpr.Method.TargetObject = new CodeThisReferenceExpression();
            evalExpr.Method.MethodName = EvalMethodName;
            evalExpr.Parameters.Add(new CodePrimitiveExpression(field));
            if (!String.IsNullOrEmpty(formatString)) {
                evalExpr.Parameters.Add(new CodePrimitiveExpression(formatString));
            }

            CodeStatementCollection evalStatements = new CodeStatementCollection();
            BuildPropertySetExpression(evalExpr, propertyName, propertyType, controlBuilder, methodStatements, evalStatements, linePragma, isEncoded, ref hasTempObject);

            // if (this.Page.GetDataItem() != null)
            CodeMethodInvokeExpression getDataItemExpr = new CodeMethodInvokeExpression();
            getDataItemExpr.Method.TargetObject = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Page");
            getDataItemExpr.Method.MethodName = GetDataItemMethodName;

            CodeConditionStatement ifStmt = new CodeConditionStatement();
            ifStmt.Condition = new CodeBinaryOperatorExpression(getDataItemExpr, 
                                                                CodeBinaryOperatorType.IdentityInequality, 
                                                                new CodePrimitiveExpression(null));
            ifStmt.TrueStatements.AddRange(evalStatements);
            statements.Add(ifStmt);
        }

        private static void BuildPropertySetExpression(CodeExpression expression, string propertyName,
            Type propertyType, ControlBuilder controlBuilder, CodeStatementCollection methodStatements, CodeStatementCollection statements, CodeLinePragma linePragma, bool isEncoded, ref bool hasTempObject) {

            if (isEncoded) {
                expression = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeTypeReferenceExpression(typeof(HttpUtility)),
                       "HtmlEncode"),
                    expression);
            }

            CodeDomUtility.CreatePropertySetStatements(methodStatements, statements,
                new CodeVariableReferenceExpression("dataBindingExpressionBuilderTarget"), propertyName, propertyType,
                expression,
                linePragma);
        }

        internal static void BuildExpressionSetup(ControlBuilder controlBuilder, CodeStatementCollection methodStatements, CodeStatementCollection statements, CodeLinePragma linePragma, bool isTwoWayBound, bool designerMode) {
            // {{controlType}} target;
            CodeVariableDeclarationStatement targetDecl = new CodeVariableDeclarationStatement(controlBuilder.ControlType, "dataBindingExpressionBuilderTarget");
            methodStatements.Add(targetDecl);

            CodeVariableReferenceExpression targetExp = new CodeVariableReferenceExpression(targetDecl.Name);

            // target = ({{controlType}}) sender;
            CodeAssignStatement setTarget = new CodeAssignStatement(targetExp,
                                                                    new CodeCastExpression(controlBuilder.ControlType,
                                                                                           new CodeArgumentReferenceExpression("sender")));
            setTarget.LinePragma = linePragma;
            statements.Add(setTarget);

            Type bindingContainerType = controlBuilder.BindingContainerType;
            CodeVariableDeclarationStatement containerDecl = new CodeVariableDeclarationStatement(bindingContainerType, "Container");
            methodStatements.Add(containerDecl);

            // {{containerType}} Container = ({{containerType}}) target.BindingContainer;
            CodeAssignStatement setContainer = new CodeAssignStatement(new CodeVariableReferenceExpression(containerDecl.Name),
                                                                       new CodeCastExpression(bindingContainerType,
                                                                                              new CodePropertyReferenceExpression(targetExp,
                                                                                                                                  "BindingContainer")));
            setContainer.LinePragma = linePragma;
            statements.Add(setContainer);
            string variableName = isTwoWayBound ? "BindItem" : "Item";
            GenerateItemTypeExpressions(controlBuilder, methodStatements, statements, linePragma, variableName);
            //Generate code for other variable as well at design time in addition to runtime variable for intellisense to work.
            if (designerMode) {
                GenerateItemTypeExpressions(controlBuilder, methodStatements, statements, linePragma, isTwoWayBound ?  "Item" : "BindItem");
            }
        }

        internal static void GenerateItemTypeExpressions(ControlBuilder controlBuilder, CodeStatementCollection declarationStatements, CodeStatementCollection codeStatements, CodeLinePragma linePragma, string variableName) {
            //Strongly Typed DataControls
            string itemType = controlBuilder.ItemType;
            CodeVariableDeclarationStatement itemTypeDecl = null;

            if (!String.IsNullOrEmpty(itemType)) {
                itemTypeDecl = new CodeVariableDeclarationStatement(itemType, variableName);
                declarationStatements.Add(itemTypeDecl);

                //Model Item = (Model)Container.DataItem; - The actual type should come from the control
                CodeAssignStatement setDataItem = new CodeAssignStatement(new CodeVariableReferenceExpression(itemTypeDecl.Name),
                                                                           new CodeCastExpression(itemType,
                                                                                                  new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("Container"),
                                                                                                                                      "DataItem")));
                setDataItem.LinePragma = linePragma;
                codeStatements.Add(setDataItem);
            }
        }

        internal override void BuildExpression(BoundPropertyEntry bpe, ControlBuilder controlBuilder,
            CodeExpression controlReference, CodeStatementCollection methodStatements, CodeStatementCollection statements, CodeLinePragma linePragma, ref bool hasTempObject) {

            BuildExpressionStatic(bpe, controlBuilder, controlReference, methodStatements, statements, linePragma, bpe.IsEncoded, ref hasTempObject);
        }

        internal static void BuildExpressionStatic(BoundPropertyEntry bpe, ControlBuilder controlBuilder,
            CodeExpression controlReference, CodeStatementCollection methodStatements, CodeStatementCollection statements, CodeLinePragma linePragma, bool isEncoded, ref bool hasTempObject) {

            CodeExpression expr = new CodeSnippetExpression(bpe.Expression);
            BuildPropertySetExpression(expr, bpe.Name, bpe.Type, controlBuilder, methodStatements, statements, linePragma, isEncoded, ref hasTempObject);
        }


        public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,
            object parsedData, ExpressionBuilderContext context) {
            Debug.Fail("This should never be called");
            return null;
        }
    }
}