void RegisterBindingInfo (ControlBuilder builder, string propName, ref string value) { string str = TrimDB (value, false); if (StrUtils.StartsWith (str, "Bind", true)) { Match match = bindRegex.Match (str); if (match.Success) { string bindingName = match.Groups [1].Value; TemplateBuilder templateBuilder = builder.ParentTemplateBuilder; if (templateBuilder == null) throw new HttpException ("Bind expression not allowed in this context."); if (templateBuilder.BindingDirection == BindingDirection.OneWay) return; string id = builder.GetAttribute ("ID"); if (String.IsNullOrEmpty (id)) throw new HttpException ("Control of type '" + builder.ControlType + "' using two-way binding on property '" + propName + "' must have an ID."); templateBuilder.RegisterBoundProperty (builder.ControlType, propName, id, bindingName); } } }
protected void CreateControlTree (ControlBuilder builder, bool inTemplate, bool childrenAsProperties) { EnsureID (builder); bool isTemplate = builder.IsTemplate; if (!isTemplate && !inTemplate) { CreateField (builder, true); } else if (!isTemplate) { bool doCheck = false; bool singleInstance = false; ControlBuilder pb = builder.ParentBuilder; TemplateBuilder tpb; while (pb != null) { tpb = pb as TemplateBuilder; if (tpb == null) { pb = pb.ParentBuilder; continue; } if (tpb.TemplateInstance == TemplateInstance.Single) singleInstance = true; break; } if (!singleInstance) builder.ID = builder.GetNextID (null); else doCheck = true; CreateField (builder, doCheck); } InitMethod (builder, isTemplate, childrenAsProperties); if (!isTemplate || builder.GetType () == typeof (RootBuilder)) CreateAssignStatementsFromAttributes (builder); if (builder.Children != null && builder.Children.Count > 0) { StringBuilder sb = new StringBuilder (); foreach (object b in builder.Children) { if (b is string) { sb.Append ((string) b); continue; } FlushText (builder, sb); if (b is ObjectTagBuilder) { ProcessObjectTag ((ObjectTagBuilder) b); } else if (b is StringPropertyBuilder) { StringPropertyBuilder pb = b as StringPropertyBuilder; if (pb.Children != null && pb.Children.Count > 0) { StringBuilder asb = new StringBuilder (); foreach (string s in pb.Children) asb.Append (s); CodeMemberMethod method = builder.Method; CodeAssignStatement assign = new CodeAssignStatement (); assign.Left = new CodePropertyReferenceExpression (ctrlVar, pb.PropertyName); assign.Right = new CodePrimitiveExpression (asb.ToString ()); method.Statements.Add (AddLinePragma (assign, builder)); } } else if (b is ContentBuilderInternal) { ContentBuilderInternal cb = (ContentBuilderInternal) b; CreateControlTree (cb, false, true); AddContentTemplateInvocation (cb, builder.Method, cb.Method.Name); continue; } // Ignore TemplateBuilders - they are processed in InitMethod else if (b is TemplateBuilder) { } else if (b is CodeRenderBuilder) { AddCodeRender (builder, (CodeRenderBuilder) b); } else if (b is DataBindingBuilder) { AddDataBindingLiteral (builder, (DataBindingBuilder) b); } else if (b is ControlBuilder) { ControlBuilder child = (ControlBuilder) b; CreateControlTree (child, inTemplate, builder.ChildrenAsProperties); AddChildCall (builder, child); continue; } else throw new Exception ("???"); ControlBuilder bldr = b as ControlBuilder; bldr.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, bldr.Method, bldr.DataBindingMethod); } FlushText (builder, sb); } ControlBuilder defaultPropertyBuilder = builder.DefaultPropertyBuilder; if (defaultPropertyBuilder != null) { CreateControlTree (defaultPropertyBuilder, false, true); AddChildCall (builder, defaultPropertyBuilder); } if (builder.HasAspCode) { CodeMemberMethod renderMethod = builder.RenderMethod; CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (); m.TargetObject = thisRef; m.MethodName = renderMethod.Name; CodeDelegateCreateExpression create = new CodeDelegateCreateExpression (); create.DelegateType = new CodeTypeReference (typeof (RenderMethod)); create.TargetObject = thisRef; create.MethodName = renderMethod.Name; CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (); invoke.Method = new CodeMethodReferenceExpression (ctrlVar, "SetRenderMethodDelegate"); invoke.Parameters.Add (create); builder.MethodStatements.Add (invoke); } if (builder is RootBuilder) if (!String.IsNullOrEmpty (parser.MetaResourceKey)) AssignPropertiesFromResources (builder, parser.BaseType, parser.MetaResourceKey); if ((!isTemplate || builder is RootBuilder) && !String.IsNullOrEmpty (builder.GetAttribute ("meta:resourcekey"))) CreateAssignStatementFromAttribute (builder, "meta:resourcekey"); if ((childrenAsProperties && builder.PropertyBuilderShouldReturnValue) || (!childrenAsProperties && typeof (Control).IsAssignableFrom (builder.ControlType))) builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar)); builder.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, builder.Method, builder.DataBindingMethod); }
void InitMethod (ControlBuilder builder, bool isTemplate, bool childrenAsProperties) { currentLocation = builder.Location; bool inBuildControlTree = builder is RootBuilder; string tailname = (inBuildControlTree ? "Tree" : ("_" + builder.ID)); // bool isProperty = builder.IsProperty; CodeMemberMethod method = new CodeMemberMethod (); builder.Method = method; builder.MethodStatements = method.Statements; method.Name = "__BuildControl" + tailname; method.Attributes = MemberAttributes.Private | MemberAttributes.Final; Type type = builder.ControlType; /* in the case this is the __BuildControlTree * method, allow subclasses to insert control * specific code. */ if (inBuildControlTree) { SetCustomAttributes (method); AddStatementsToInitMethodTop (builder, method); } if (builder.HasAspCode) { CodeMemberMethod renderMethod = new CodeMemberMethod (); builder.RenderMethod = renderMethod; renderMethod.Name = "__Render" + tailname; renderMethod.Attributes = MemberAttributes.Private | MemberAttributes.Final; CodeParameterDeclarationExpression arg1 = new CodeParameterDeclarationExpression (); arg1.Type = new CodeTypeReference (typeof (HtmlTextWriter)); arg1.Name = "__output"; CodeParameterDeclarationExpression arg2 = new CodeParameterDeclarationExpression (); arg2.Type = new CodeTypeReference (typeof (Control)); arg2.Name = "parameterContainer"; renderMethod.Parameters.Add (arg1); renderMethod.Parameters.Add (arg2); mainClass.Members.Add (renderMethod); } if (childrenAsProperties || type == null) { string typeString; bool isGlobal = true; bool returnsControl; if (builder is RootBuilder) { typeString = parser.ClassName; isGlobal = false; returnsControl = false; } else { returnsControl = builder.PropertyBuilderShouldReturnValue; if (type != null && builder.IsProperty && !typeof (ITemplate).IsAssignableFrom (type)) { typeString = type.FullName; isGlobal = !type.IsPrimitive; } else typeString = "System.Web.UI.Control"; ProcessTemplateChildren (builder); } CodeTypeReference ctrlTypeRef = new CodeTypeReference (typeString); if (isGlobal) ctrlTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference; if (returnsControl) { method.ReturnType = ctrlTypeRef; // $controlType _ctrl = new $controlType ($parameters); // method.Statements.Add (CreateControlVariable (type, builder, method, ctrlTypeRef)); } else method.Parameters.Add (new CodeParameterDeclarationExpression (typeString, "__ctrl")); } else { CodeTypeReference ctrlTypeRef = new CodeTypeReference (type.FullName); if (!type.IsPrimitive) ctrlTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference; if (typeof (Control).IsAssignableFrom (type)) method.ReturnType = ctrlTypeRef; // $controlType _ctrl = new $controlType ($parameters); // method.Statements.Add (AddLinePragma (CreateControlVariable (type, builder, method, ctrlTypeRef), builder)); // this.$builderID = _ctrl; // CodeFieldReferenceExpression builderID = new CodeFieldReferenceExpression (); builderID.TargetObject = thisRef; builderID.FieldName = builder.ID; CodeAssignStatement assign = new CodeAssignStatement (); assign.Left = builderID; assign.Right = ctrlVar; method.Statements.Add (AddLinePragma (assign, builder)); if (typeof (UserControl).IsAssignableFrom (type)) { CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression (); mref.TargetObject = builderID; mref.MethodName = "InitializeAsUserControl"; CodeMethodInvokeExpression initAsControl = new CodeMethodInvokeExpression (mref); initAsControl.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page")); method.Statements.Add (initAsControl); } if (builder.ParentTemplateBuilder is System.Web.UI.WebControls.ContentBuilderInternal) { PropertyInfo pi; try { pi = type.GetProperty ("TemplateControl"); } catch (Exception) { pi = null; } if (pi != null && pi.CanWrite) { // __ctrl.TemplateControl = this; assign = new CodeAssignStatement (); assign.Left = new CodePropertyReferenceExpression (ctrlVar, "TemplateControl");; assign.Right = thisRef; method.Statements.Add (assign); } } // _ctrl.SkinID = $value // _ctrl.ApplyStyleSheetSkin (this); // // the SkinID assignment needs to come // before the call to // ApplyStyleSheetSkin, for obvious // reasons. We skip SkinID in // CreateAssignStatementsFromAttributes // below. // string skinid = builder.GetAttribute ("skinid"); if (!String.IsNullOrEmpty (skinid)) CreateAssignStatementFromAttribute (builder, "skinid"); if (typeof (WebControl).IsAssignableFrom (type)) { CodeMethodInvokeExpression applyStyleSheetSkin = new CodeMethodInvokeExpression (ctrlVar, "ApplyStyleSheetSkin"); if (typeof (Page).IsAssignableFrom (parser.BaseType)) applyStyleSheetSkin.Parameters.Add (thisRef); else applyStyleSheetSkin.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page")); method.Statements.Add (applyStyleSheetSkin); } // Process template children before anything else ProcessTemplateChildren (builder); // process ID here. It should be set before any other attributes are // assigned, since the control code may rely on ID being set. We // skip ID in CreateAssignStatementsFromAttributes string ctl_id = builder.GetAttribute ("id"); if (ctl_id != null && ctl_id.Length != 0) CreateAssignStatementFromAttribute (builder, "id"); if (typeof (ContentPlaceHolder).IsAssignableFrom (type)) { List <string> placeHolderIds = MasterPageContentPlaceHolders; string cphID = builder.ID; if (!placeHolderIds.Contains (cphID)) placeHolderIds.Add (cphID); CodeConditionStatement condStatement; // Add the __Template_* field string templateField = "__Template_" + cphID; CodeMemberField fld = new CodeMemberField (typeof (ITemplate), templateField); fld.Attributes = MemberAttributes.Private; mainClass.Members.Add (fld); CodeFieldReferenceExpression templateID = new CodeFieldReferenceExpression (); templateID.TargetObject = thisRef; templateID.FieldName = templateField; CreateContentPlaceHolderTemplateProperty (templateField, "Template_" + cphID); // if ((this.ContentTemplates != null)) { // this.__Template_$builder.ID = ((System.Web.UI.ITemplate)(this.ContentTemplates["$builder.ID"])); // } // CodeFieldReferenceExpression contentTemplates = new CodeFieldReferenceExpression (); contentTemplates.TargetObject = thisRef; contentTemplates.FieldName = "ContentTemplates"; CodeIndexerExpression indexer = new CodeIndexerExpression (); indexer.TargetObject = new CodePropertyReferenceExpression (thisRef, "ContentTemplates"); indexer.Indices.Add (new CodePrimitiveExpression (cphID)); assign = new CodeAssignStatement (); assign.Left = templateID; assign.Right = new CodeCastExpression (new CodeTypeReference (typeof (ITemplate)), indexer); condStatement = new CodeConditionStatement (new CodeBinaryOperatorExpression (contentTemplates, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null)), assign); method.Statements.Add (condStatement); // if ((this.__Template_mainContent != null)) { // this.__Template_mainContent.InstantiateIn(__ctrl); // } // and also set things up such that any additional code ends up in: // else { // ... // } // CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression (); methodRef.TargetObject = templateID; methodRef.MethodName = "InstantiateIn"; CodeMethodInvokeExpression instantiateInInvoke; instantiateInInvoke = new CodeMethodInvokeExpression (methodRef, ctrlVar); condStatement = new CodeConditionStatement (new CodeBinaryOperatorExpression (templateID, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null)), new CodeExpressionStatement (instantiateInInvoke)); method.Statements.Add (condStatement); // this is the bit that causes the following stuff to end up in the else { } builder.MethodStatements = condStatement.FalseStatements; } } if (inBuildControlTree) AddStatementsToInitMethodBottom (builder, method); mainClass.Members.Add (method); }
void CreateAssignStatementFromAttribute (ControlBuilder builder, string id) { EventInfo [] ev_info = null; Type type = builder.ControlType; string attvalue = builder.GetAttribute (id); if (id.Length > 2 && String.Compare (id.Substring (0, 2), "ON", true, Helpers.InvariantCulture) == 0){ if (ev_info == null) ev_info = type.GetEvents (); string id_as_event = id.Substring (2); foreach (EventInfo ev in ev_info){ if (InvariantCompareNoCase (ev.Name, id_as_event)){ AddEventAssign (builder.Method, builder, ev.Name, ev.EventHandlerType, attvalue); return; } } } if (String.Compare (id, "meta:resourcekey", StringComparison.OrdinalIgnoreCase) == 0) { AssignPropertiesFromResources (builder, attvalue); return; } int hyphen = id.IndexOf ('-'); string alt_id = id; if (hyphen != -1) alt_id = id.Substring (0, hyphen); MemberInfo fop = GetFieldOrProperty (type, alt_id); if (fop != null) { if (ProcessPropertiesAndFields (builder, fop, id, attvalue, null)) return; } if (!typeof (IAttributeAccessor).IsAssignableFrom (type)) throw new ParseException (builder.Location, "Unrecognized attribute: " + id); CodeMemberMethod method = builder.Method; bool isDatabound = BaseParser.IsDataBound (attvalue); bool isExpression = !isDatabound && BaseParser.IsExpression (attvalue); if (isDatabound) { string value = attvalue.Substring (3, attvalue.Length - 5).Trim (); CodeExpression valueExpression = null; if (startsWithBindRegex.Match (value).Success) valueExpression = CreateEvalInvokeExpression (bindRegexInValue, value, true); else if (StrUtils.StartsWith (value, "Eval", true)) valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false); if (valueExpression == null && value != null && value.Trim () != String.Empty) valueExpression = new CodeSnippetExpression (value); CreateDBAttributeMethod (builder, id, valueExpression); } else { CodeCastExpression cast; CodeMethodReferenceExpression methodExpr; CodeMethodInvokeExpression expr; cast = new CodeCastExpression (typeof (IAttributeAccessor), ctrlVar); methodExpr = new CodeMethodReferenceExpression (cast, "SetAttribute"); expr = new CodeMethodInvokeExpression (methodExpr); expr.Parameters.Add (new CodePrimitiveExpression (id)); CodeExpression valueExpr = null; if (isExpression) valueExpr = CompileExpression (null, typeof (string), attvalue, true); if (valueExpr == null) valueExpr = new CodePrimitiveExpression (attvalue); expr.Parameters.Add (valueExpr); method.Statements.Add (AddLinePragma (expr, builder)); } }