154 lines
9.0 KiB
C#
154 lines
9.0 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <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;
|
||
|
}
|
||
|
}
|
||
|
}
|