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;
}
}
}
|