BaseTemplateCodeDomTreeGenerator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / Compilation / BaseTemplateCodeDomTreeGenerator.cs / 1 / BaseTemplateCodeDomTreeGenerator.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Compilation { 
 
    using System;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.Reflection;
    using System.IO;
    using System.ComponentModel; 
    using System.CodeDom;
    using System.CodeDom.Compiler; 
    using System.Globalization; 
    using System.Web.UI;
    using System.Web.Util; 
    using System.Web.Configuration;
    using System.ComponentModel.Design;
    using Debug=System.Web.Util.Debug;
 
    internal abstract class BaseTemplateCodeDomTreeGenerator : BaseCodeDomTreeGenerator {
 
        protected static readonly string buildMethodPrefix = "__BuildControl"; 
        protected static readonly string extractTemplateValuesMethodPrefix = "__ExtractValues";
        protected static readonly string templateSourceDirectoryName = "AppRelativeTemplateSourceDirectory"; 
        protected static readonly string applyStyleSheetMethodName = "ApplyStyleSheetSkin";
        protected static readonly string pagePropertyName = "Page";
        internal const string skinIDPropertyName = "SkinID";
        private const string _localVariableRef = "__ctrl"; 

        private TemplateParser _parser; 
        private int _controlCount; 

        // Minimum literal string length for it to be placed in the resource 
        private const int minLongLiteralStringLength = 256;
        private const string renderMethodParameterName = "__w";

        // Used in designer mode 
        internal const string tempObjectVariable = "__o";
 
 
        /*
         * Set some fields that are needed for code generation 
         */
        internal BaseTemplateCodeDomTreeGenerator(TemplateParser parser) : base(parser) {
            _parser = parser;
        } 

        private TemplateParser Parser { 
            get { 
                return _parser;
            } 
        }

        private CodeStatement GetOutputWriteStatement(CodeExpression expr) {
 
            CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression();
            CodeExpressionStatement call = new CodeExpressionStatement(methodInvoke); 
            methodInvoke.Method.TargetObject = new CodeArgumentReferenceExpression(renderMethodParameterName); 
            methodInvoke.Method.MethodName = "Write";
 
            methodInvoke.Parameters.Add(expr);

            return call;
        } 

 
        ///  
        ///     Append an output.Write() statement to a Render method
        ///  
        private void AddOutputWriteStatement(CodeStatementCollection methodStatements,
                                     CodeExpression expr,
                                     CodeLinePragma linePragma) {
 
            CodeStatement outputWriteStmt = GetOutputWriteStatement(expr);
            if (linePragma != null) 
                outputWriteStmt.LinePragma = linePragma; 

            methodStatements.Add(outputWriteStmt); 
        }

        private void AddOutputWriteStringStatement(CodeStatementCollection methodStatements,
                                     String s) { 

            if (!UseResourceLiteralString(s)) { 
                AddOutputWriteStatement(methodStatements, new CodePrimitiveExpression(s), null); 
                return;
            } 

            // Add the string to the resource builder, and get back its offset/size
            int offset, size;
            bool fAsciiOnly; 
            _stringResourceBuilder.AddString(s, out offset, out size, out fAsciiOnly);
 
            // e.g. WriteUTF8ResourceString(output, 314, 20); 
            CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression();
            CodeExpressionStatement call = new CodeExpressionStatement(methodInvoke); 
            methodInvoke.Method.TargetObject = new CodeThisReferenceExpression();
            methodInvoke.Method.MethodName = "WriteUTF8ResourceString";
            methodInvoke.Parameters.Add(new CodeArgumentReferenceExpression(renderMethodParameterName));
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(offset)); 
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(size));
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(fAsciiOnly)); 
            methodStatements.Add(call); 
        }
 
        private static void BuildAddParsedSubObjectStatement(
                    CodeStatementCollection statements, CodeExpression ctrlToAdd, CodeLinePragma linePragma, CodeExpression ctrlRefExpr, ref bool gotParserVariable) {

            if (!gotParserVariable) { 
                // e.g. IParserAccessor __parser = ((IParserAccessor)__ctrl);
                CodeVariableDeclarationStatement parserDeclaration = new CodeVariableDeclarationStatement(); 
                parserDeclaration.Name = "__parser"; 
                parserDeclaration.Type = new CodeTypeReference(typeof(IParserAccessor));
                parserDeclaration.InitExpression = new CodeCastExpression( 
                                                        typeof(IParserAccessor),
                                                        ctrlRefExpr);
                statements.Add(parserDeclaration);
                gotParserVariable = true; 
            }
 
            // e.g. __parser.AddParsedSubObject({{controlName}}); 
            CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression("__parser"), "AddParsedSubObject"); 
            methCallExpression.Parameters.Add(ctrlToAdd);
            CodeExpressionStatement methCallStatement = new CodeExpressionStatement(methCallExpression);
            methCallStatement.LinePragma = linePragma;
 
            statements.Add(methCallStatement);
        } 
 
        internal virtual CodeExpression BuildPagePropertyReferenceExpression() {
            return new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), pagePropertyName); 
        }

        /*
         * Build the data tree for a control's build method 
         */
        protected CodeMemberMethod BuildBuildMethod(ControlBuilder builder, bool fTemplate, 
            bool fInTemplate, bool topLevelControlInTemplate, PropertyEntry pse, bool fControlSkin) { 

            Debug.Assert(builder.ServiceProvider == null); 

            ServiceContainer container = new ServiceContainer();
            container.AddService(typeof(IFilterResolutionService), HttpCapabilitiesBase.EmptyHttpCapabilitiesBase);
 
            try {
                builder.SetServiceProvider(container); 
                builder.EnsureEntriesSorted(); 
            }
            finally { 
                builder.SetServiceProvider(null);
            }

            string methodName = GetMethodNameForBuilder(buildMethodPrefix, builder); 
            Type ctrlType = GetCtrlTypeForBuilder(builder, fTemplate);
            bool fStandardControl = false; 
            bool fControlFieldDeclared = false; 

            CodeMemberMethod method = new CodeMemberMethod(); 
            AddDebuggerNonUserCodeAttribute(method);
            method.Name = methodName;
            method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
 
            _sourceDataClass.Members.Add(method);
 
            // If it's for a template or a r/o complex prop, pass a parameter of the control's type 
            ComplexPropertyEntry cpse = pse as ComplexPropertyEntry;
            if (fTemplate || (cpse != null && cpse.ReadOnly)) { 
                if (builder is RootBuilder)
                    method.Parameters.Add(new CodeParameterDeclarationExpression(_sourceDataClass.Name, "__ctrl"));
                else
                    method.Parameters.Add(new CodeParameterDeclarationExpression(ctrlType, "__ctrl")); 
            }
            else { 
                // If it's a standard control, return it from the method 
                if (typeof(Control).IsAssignableFrom(builder.ControlType)) {
                    fStandardControl = true; 
                }

                Debug.Assert(builder.ControlType != null);
                if (builder.ControlType != null) { 
                    if (fControlSkin) {
                        // ReturnType needs to be of type Control in a skin file to match 
                        // the controlskin delegate. 
                        if (fStandardControl) {
                            method.ReturnType = new CodeTypeReference(typeof(Control)); 
                        }
                    }
                    else {
                        PartialCachingAttribute cacheAttrib = (PartialCachingAttribute) 
                            TypeDescriptor.GetAttributes(builder.ControlType)[typeof(PartialCachingAttribute)];
                        if (cacheAttrib != null) { 
                            method.ReturnType = new CodeTypeReference(typeof(Control)); 
                        }
                        else { 
                            // Otherwise the return type is always the actual component type.
                            method.ReturnType = new CodeTypeReference(builder.ControlType,
                                CodeTypeReferenceOptions.GlobalReference);
                        } 
                    }
                } 
 
                // A control field declaration is required, this field will be returned
                // in the method. 
                fControlFieldDeclared = true;
            }

            // Add a control parameter if it's a ControlSkin 
            if (fControlSkin) {
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control).FullName, "ctrl")); 
            } 

            BuildBuildMethodInternal(builder, builder.ControlType, fInTemplate, topLevelControlInTemplate, pse, 
                method.Statements, fStandardControl, fControlFieldDeclared, null, fControlSkin);

            return method;
        } 

        /* Helper method to generate the content of the control's build method 
         *  Type _ctrl; 
         *  _ctrl = new Type();
         *      ... 
         *  return _ctrl;
         */
        private void BuildBuildMethodInternal(ControlBuilder builder, Type ctrlType, bool fInTemplate,
            bool topLevelControlInTemplate, PropertyEntry pse, CodeStatementCollection statements, 
            bool fStandardControl, bool fControlFieldDeclared, string deviceFilter, bool fControlSkin) {
 
            // Same linePragma in the entire build method 
            CodeLinePragma linePragma = CreateCodeLinePragma(builder);
 
            CodeObjectCreateExpression newExpr;
            CodeExpressionStatement methCallStatement;
            CodeMethodInvokeExpression methCallExpression;
 
            CodeExpression ctrlRefExpr;
 
            if (fControlSkin) { 
                CodeCastExpression cast = new CodeCastExpression(builder.ControlType.FullName,
                                           new CodeArgumentReferenceExpression("ctrl")); 
                statements.Add(new CodeVariableDeclarationStatement(builder.ControlType.FullName, "__ctrl", cast));
                ctrlRefExpr = new CodeVariableReferenceExpression("__ctrl");
            }
            // Not a control. ie. it's for a template or a r/o complex prop, 
            else if (!fControlFieldDeclared) {
                ctrlRefExpr = new CodeArgumentReferenceExpression("__ctrl"); 
            } 
            else {
                CodeTypeReference ctrlTypeRef = new CodeTypeReference(ctrlType, 
                    CodeTypeReferenceOptions.GlobalReference);

                newExpr = new CodeObjectCreateExpression(ctrlTypeRef);
 
                // If it has a ConstructorNeedsTagAttribute, it needs a tag name
                ConstructorNeedsTagAttribute cnta = (ConstructorNeedsTagAttribute) 
                    TypeDescriptor.GetAttributes(ctrlType)[typeof(ConstructorNeedsTagAttribute)]; 

                if (cnta != null && cnta.NeedsTag) { 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(builder.TagName));
                }

                // If it's for a DataBoundLiteralControl, pass it the number of 
                // entries in the constructor
                DataBoundLiteralControlBuilder dataBoundBuilder = builder as DataBoundLiteralControlBuilder; 
                if (dataBoundBuilder != null) { 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(
                        dataBoundBuilder.GetStaticLiteralsCount())); 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(
                        dataBoundBuilder.GetDataBoundLiteralCount()));
                }
 
                // e.g. {{controlTypeName}} __ctrl;
                statements.Add(new CodeVariableDeclarationStatement(ctrlTypeRef, "__ctrl")); 
                ctrlRefExpr = new CodeVariableReferenceExpression("__ctrl"); 

                // e.g. __ctrl = new {{controlTypeName}}(); 
                CodeAssignStatement setCtl = new CodeAssignStatement(ctrlRefExpr, newExpr);
                setCtl.LinePragma = linePragma;
                statements.Add(setCtl);
 
                if (!builder.IsGeneratedID) {
                    // Assign the local control reference to the global control variable 
                    CodeFieldReferenceExpression ctrlNameExpr = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), builder.ID); 

                    // e.g. {{controlName}} = __ctrl; 
                    CodeAssignStatement underscoreCtlSet = new CodeAssignStatement(ctrlNameExpr, ctrlRefExpr);
                    statements.Add(underscoreCtlSet);
                }
 
                // Don't do this if the control is itself a TemplateControl, in which case it
                // will point its TemplateControl property to itself (instead of its parent 
                // TemplateControl).  VSWhidbey 214356. 
                if (topLevelControlInTemplate && !typeof(TemplateControl).IsAssignableFrom(ctrlType)) {
                    statements.Add(BuildTemplatePropertyStatement(ctrlRefExpr)); 
                }

                if (fStandardControl) {
                    // e.g. __ctrl.SkinID = {{skinID}}; 
                    if (builder.SkinID != null) {
                        CodeAssignStatement set = new CodeAssignStatement(); 
                        set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, skinIDPropertyName); 
                        set.Right = new CodePrimitiveExpression(builder.SkinID);
                        statements.Add(set); 
                    }

                    // e.g. __ctrl.ApplyStyleSheetSkin(this);
                    if (ThemeableAttribute.IsTypeThemeable(ctrlType)) { 
                        // e.g. __ctrl.ApplyStyleSheetSkin(this.Page);
                        CodeMethodInvokeExpression applyStyleSheetExpr = new CodeMethodInvokeExpression(ctrlRefExpr, applyStyleSheetMethodName); 
                        applyStyleSheetExpr.Parameters.Add(BuildPagePropertyReferenceExpression()); 

                        statements.Add(applyStyleSheetExpr); 
                    }
                }
            }
 
            // Process the templates
            if (builder.TemplatePropertyEntries.Count > 0) { 
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts; 
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null;

                foreach (TemplatePropertyEntry pseSub in builder.TemplatePropertyEntries) { 
                    currentStmts = nextStmts;
 
                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts); 

                    string controlName = pseSub.Builder.ID; 
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                    newDelegate.DelegateType = new CodeTypeReference(typeof(BuildTemplateMethod));
                    newDelegate.TargetObject = new CodeThisReferenceExpression();
                    newDelegate.MethodName = buildMethodPrefix + controlName; 

                    CodeAssignStatement set = new CodeAssignStatement(); 
                    if (pseSub.PropertyInfo != null) { 
                        set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);
                    } 
                    else {
                        set.Left = new CodeFieldReferenceExpression(ctrlRefExpr, pseSub.Name);
                    }
 
                    if (pseSub.BindableTemplate) {
                        // e.g. __ctrl.{{templateName}} = new CompiledBindableTemplateBuilder( 
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}}), 
                        // e.g.     new ExtractTemplateValuesMethod(this.__ExtractValues {{controlName}}));
                        CodeExpression newExtractValuesDelegate; 
                        if (pseSub.Builder.HasTwoWayBoundProperties) {
                            newExtractValuesDelegate = new CodeDelegateCreateExpression();
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).DelegateType = new CodeTypeReference(typeof(ExtractTemplateValuesMethod));
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).TargetObject = new CodeThisReferenceExpression(); 
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).MethodName = extractTemplateValuesMethodPrefix + controlName;
                        } 
                        else { 
                            newExtractValuesDelegate = new CodePrimitiveExpression(null);
                        } 

                        newExpr = new CodeObjectCreateExpression(typeof(CompiledBindableTemplateBuilder));
                        newExpr.Parameters.Add(newDelegate);
                        newExpr.Parameters.Add(newExtractValuesDelegate); 

                    } 
                    else { 
                        // e.g. __ctrl.{{templateName}} = new CompiledTemplateBuilder(
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}})); 
                        newExpr = new CodeObjectCreateExpression(typeof(CompiledTemplateBuilder));
                        newExpr.Parameters.Add(newDelegate);

                    } 
                    set.Right = newExpr;
                    set.LinePragma = CreateCodeLinePragma(pseSub.Builder); 
                    currentStmts.Add(set); 
                }
            } 

            // Is this BuilderData for a declarative control?  If so initialize it (75330)
            // Only do this is the control field has been declared (i.e. not with templates)
            if (typeof(UserControl).IsAssignableFrom(ctrlType) && fControlFieldDeclared && !fControlSkin) { 
                // e.g. _ctrl.InitializeAsUserControl(Context, Page);
                methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "InitializeAsUserControl"); 
                methCallExpression.Parameters.Add(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), pagePropertyName)); 
                methCallStatement = new CodeExpressionStatement(methCallExpression);
                methCallStatement.LinePragma = linePragma; 
                statements.Add(methCallStatement);
            }

            // Process the simple attributes 
            if (builder.SimplePropertyEntries.Count > 0) {
                // Used to deal with the device filter conditionals 
                CodeStatementCollection currentStmts; 
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null; 

                foreach (SimplePropertyEntry pseSub in builder.SimplePropertyEntries) {
                    currentStmts = nextStmts;
 
                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts);
 
                    CodeStatement statement = pseSub.GetCodeStatement(this, ctrlRefExpr); 
                    statement.LinePragma = linePragma;
                    currentStmts.Add(statement); 
                }
            }

            // Call the helper method for allowing page developers to customize culture settings 
            if (typeof(Page).IsAssignableFrom(ctrlType) && !fControlSkin) {
                // e.g. this.InitializeCulture(); 
                methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InitializeCulture"); 
                methCallStatement = new CodeExpressionStatement(methCallExpression);
                methCallStatement.LinePragma = linePragma; 
                statements.Add(methCallStatement);
            }

            // Automatic template support (i.e. ) 
            CodeMethodInvokeExpression instantiateTemplateExpr = null;
            CodeConditionStatement templateIfStmt = null; 
            CodeStatementCollection buildSubControlBlock = statements; 
            string autoTemplateName = null;
            if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) { 

                string templateName = ((System.Web.UI.WebControls.ContentPlaceHolderBuilder)builder).Name;
                autoTemplateName = MasterPageControlBuilder.AutoTemplatePrefix + templateName;
 
                Debug.Assert(autoTemplateName != null && autoTemplateName.Length > 0, "Template Name is empty.");
 
                // Generate a private field and public property for the ITemplate 
                string fieldName = "__"+ autoTemplateName;
 
                Type containerType = builder.BindingContainerType;
                // Use the base class or template type if INamingContainer cannot be found.
                if (!typeof(INamingContainer).IsAssignableFrom(containerType)) {
                    if (typeof(INamingContainer).IsAssignableFrom(Parser.BaseType)) { 
                        containerType = Parser.BaseType;
                    } 
                    else { 
                        // This should not occur as all base classes are namingcontainers.
                        Debug.Assert(false, "baseClassType is not an INamingContainer"); 
                        containerType = typeof(System.Web.UI.Control);
                    }
                }
 
                CodeAttributeDeclarationCollection attrDeclarations = new CodeAttributeDeclarationCollection();
 
                CodeAttributeDeclaration templateContainerAttrDeclaration = new CodeAttributeDeclaration( 
                    "TemplateContainer",
                    new CodeAttributeArgument[] { 
                        new CodeAttributeArgument(new CodeTypeOfExpression(containerType))});

                attrDeclarations.Add(templateContainerAttrDeclaration);
 
                // If the template control is in a template, assume its container allows multiple instances,
                // otherwise set the TemplateInstanceAttribute 
                if (fInTemplate == false) { 
                    CodeAttributeDeclaration templateInstanceAttrDeclaration = new CodeAttributeDeclaration(
                        "TemplateInstanceAttribute", 
                        new CodeAttributeArgument[] {
                            new CodeAttributeArgument(
                                new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(TemplateInstance)),
                                                                 "Single"))}); 
                    attrDeclarations.Add(templateInstanceAttrDeclaration);
                } 
 
                BuildFieldAndAccessorProperty(autoTemplateName, fieldName, typeof(ITemplate), false /*fStatic*/, attrDeclarations);
                CodeExpression templateFieldRef = new CodeFieldReferenceExpression( 
                    new CodeThisReferenceExpression(), fieldName);

                if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) {
                    // We generate something like this: 
                    // if (this.ContentTemplates != null) {
                    //     this.__Template_TestTemplate = (ITemplate)this.ContentTemplates[{templateName}]; 
                    // } 
                    CodePropertyReferenceExpression contentTemplatesFieldRef =
                        new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ContentTemplates"); 

                    CodeAssignStatement setStatement = new CodeAssignStatement();
                    setStatement.Left = templateFieldRef;
                    setStatement.Right = new CodeCastExpression(typeof(ITemplate), new CodeIndexerExpression(contentTemplatesFieldRef, 
                                                                                       new CodePrimitiveExpression(templateName)));
 
                    CodeConditionStatement contentTemplateIfStmt = new CodeConditionStatement(); 

                    CodeBinaryOperatorExpression contentNullCheckExpr = new CodeBinaryOperatorExpression(contentTemplatesFieldRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)); 

                    CodeMethodInvokeExpression removeExpr = new CodeMethodInvokeExpression(contentTemplatesFieldRef, "Remove");
                    removeExpr.Parameters.Add(new CodePrimitiveExpression(templateName));
 
                    contentTemplateIfStmt.Condition = contentNullCheckExpr;
                    contentTemplateIfStmt.TrueStatements.Add(setStatement); 
 
                    statements.Add(contentTemplateIfStmt);
                } 

                // We generate something like this:
                // if ((this.__Template_TestTemplate != null)) {
                //     this.__Template_TestTemplate.InstantiateIn(__ctrl); 
                // }
                // else { 
                //     // normal sub control building code 
                // }
                instantiateTemplateExpr = new CodeMethodInvokeExpression(templateFieldRef, "InstantiateIn"); 
                instantiateTemplateExpr.Parameters.Add(ctrlRefExpr);

                templateIfStmt = new CodeConditionStatement();
                templateIfStmt.Condition = new CodeBinaryOperatorExpression(templateFieldRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)); 
                templateIfStmt.TrueStatements.Add(new CodeExpressionStatement(instantiateTemplateExpr));
                buildSubControlBlock = templateIfStmt.FalseStatements; 
                statements.Add(templateIfStmt); 
            }
 
            ICollection contentBuilderEntries = null;
            if (builder is FileLevelPageControlBuilder) {
                contentBuilderEntries = ((FileLevelPageControlBuilder)builder).ContentBuilderEntries;
 
                if (contentBuilderEntries != null) {
                    CodeStatementCollection currentStmts; 
                    CodeStatementCollection nextStmts = statements; 
                    PropertyEntry previous = null;
 
                    foreach (TemplatePropertyEntry entry in contentBuilderEntries) {
                        System.Web.UI.WebControls.ContentBuilderInternal child =
                            (System.Web.UI.WebControls.ContentBuilderInternal)entry.Builder;
 
                        currentStmts = nextStmts;
 
                        HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStmts, out nextStmts); 

                        string controlName = child.ID; 
                        string contentPlaceHolderID = child.ContentPlaceHolder;

                        CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                        newDelegate.DelegateType = new CodeTypeReference(typeof(BuildTemplateMethod)); 
                        newDelegate.TargetObject = new CodeThisReferenceExpression();
                        newDelegate.MethodName = buildMethodPrefix + controlName; 
 
                        // e.g. this.AddContentTemplate(contentPlaceHolderID, new CompiledTemplateBuilder(
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}})); 
                        CodeObjectCreateExpression cocExpr = new CodeObjectCreateExpression(typeof(CompiledTemplateBuilder));
                        cocExpr.Parameters.Add(newDelegate);

                        CodeMethodInvokeExpression cmiExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "AddContentTemplate"); 
                        cmiExpression.Parameters.Add(new CodePrimitiveExpression(contentPlaceHolderID));
                        cmiExpression.Parameters.Add(cocExpr); 
 
                        CodeExpressionStatement ceStatement = new CodeExpressionStatement(cmiExpression);
                        ceStatement.LinePragma = CreateCodeLinePragma((ControlBuilder)child); 

                        currentStmts.Add(ceStatement);
                    }
                } 
            }
 
            if (builder is DataBoundLiteralControlBuilder) { 

                // If it's a DataBoundLiteralControl, build it by calling SetStaticString 
                // on all the static literal strings.
                int i = -1;
                foreach (object child in builder.SubBuilders) {
                    i++; 

                    // Ignore it if it's null 
                    if (child == null) 
                        continue;
 
                    // Only deal with the strings here, which have even index
                    if (i % 2 == 1) {
                        Debug.Assert(child is CodeBlockBuilder, "child is CodeBlockBuilder");
                        continue; 
                    }
 
                    string s = (string) child; 

                    // e.g. __ctrl.SetStaticString(3, "literal string"); 
                    methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "SetStaticString");
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(i/2));
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(s));
                    statements.Add(new CodeExpressionStatement(methCallExpression)); 
                }
            } 
            // Process the children 
            else if (builder.SubBuilders != null) {
 
                bool gotParserVariable = false;
                int localVarIndex = 1;

                foreach (object child in builder.SubBuilders) { 
                    if (child is ControlBuilder && !(child is CodeBlockBuilder) && !(child is System.Web.UI.WebControls.ContentBuilderInternal)) {
                        ControlBuilder ctrlBuilder = (ControlBuilder) child; 
 
                        if (fControlSkin) {
                            throw new HttpParseException(SR.GetString(SR.ControlSkin_cannot_contain_controls), 
                                null,
                                builder.VirtualPath, null, builder.Line);
                        }
 
                        PartialCachingAttribute cacheAttrib = (PartialCachingAttribute)
                            TypeDescriptor.GetAttributes(ctrlBuilder.ControlType)[typeof(PartialCachingAttribute)]; 
 
                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + ctrlBuilder.ID); 
                        methCallStatement = new CodeExpressionStatement(methCallExpression);

                        if (cacheAttrib == null) {
                            string localVariableRef = _localVariableRef + (localVarIndex++).ToString(CultureInfo.InvariantCulture); 

                            // Variable reference to the local control variable 
                            CodeVariableReferenceExpression childCtrlRefExpr = new CodeVariableReferenceExpression(localVariableRef); 

                            // e.g. {{controlTypeName}} ctrl5; 
                            CodeTypeReference ctrlTypeReference =
                                new CodeTypeReference(ctrlBuilder.ControlType, CodeTypeReferenceOptions.GlobalReference);
                            buildSubControlBlock.Add(new CodeVariableDeclarationStatement(ctrlTypeReference, localVariableRef));
 
                            // e.g. ctrl5 = __BuildControl__control6();
                            CodeAssignStatement setCtl = new CodeAssignStatement(childCtrlRefExpr, methCallExpression); 
                            setCtl.LinePragma = linePragma; 
                            buildSubControlBlock.Add(setCtl);
 
                            // If there is no caching on the control, just create it and add it
                            // e.g. __parser.AddParsedSubObject(ctrl5);
                            BuildAddParsedSubObjectStatement(
                                buildSubControlBlock, 
                                childCtrlRefExpr,
                                linePragma, 
                                ctrlRefExpr, 
                                ref gotParserVariable);
                        } 
                        else {
                            // The control's output is getting cached.  Call
                            // StaticPartialCachingControl.BuildCachedControl to do the work.
 
                            // e.g. StaticPartialCachingControl.BuildCachedControl(__ctrl, Request, "e4192e6d-cbe0-4df5-b516-682c10415590", __pca, new System.Web.UI.BuildMethod(this.__BuildControlt1));
                            CodeMethodInvokeExpression call = new CodeMethodInvokeExpression(); 
                            call.Method.TargetObject = new CodeTypeReferenceExpression(typeof(System.Web.UI.StaticPartialCachingControl)); 
                            call.Method.MethodName = "BuildCachedControl";
                            call.Parameters.Add(ctrlRefExpr); 
                            call.Parameters.Add(new CodePrimitiveExpression(ctrlBuilder.ID));

                            // If the caching is shared, use the type of the control as the key
                            // otherwise, generate a guid 
                            if (cacheAttrib.Shared) {
                                call.Parameters.Add(new CodePrimitiveExpression( 
                                    ctrlBuilder.ControlType.GetHashCode().ToString(CultureInfo.InvariantCulture))); 
                            }
                            else 
                                call.Parameters.Add(new CodePrimitiveExpression(Guid.NewGuid().ToString()));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.Duration));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByParams));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByControls)); 
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByCustom));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.SqlDependency)); 
                            CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression(); 
                            newDelegate.DelegateType = new CodeTypeReference(typeof(BuildMethod));
                            newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                            newDelegate.MethodName = buildMethodPrefix + ctrlBuilder.ID;
                            call.Parameters.Add(newDelegate);
                            buildSubControlBlock.Add(new CodeExpressionStatement(call));
                        } 

                    } 
                    else if (child is string && !builder.HasAspCode) { 

                        // VSWhidbey 276806: if the control cares about the inner text (builder does not allow whitespace literals) 
                        // the inner literals should be added to the control.
                        if (!fControlSkin || !builder.AllowWhitespaceLiterals()) {
                            string s = (string) child;
                            CodeExpression expr; 

                            if (!UseResourceLiteralString(s)) { 
                                // e.g. ((IParserAccessor)__ctrl).AddParsedSubObject(new LiteralControl({{@QuoteCString(text)}})); 
                                newExpr = new CodeObjectCreateExpression(typeof(LiteralControl));
                                newExpr.Parameters.Add(new CodePrimitiveExpression(s)); 
                                expr = newExpr;
                            }
                            else {
                                // Add the string to the resource builder, and get back its offset/size 
                                int offset, size;
                                bool fAsciiOnly; 
                                _stringResourceBuilder.AddString(s, out offset, out size, out fAsciiOnly); 

                                methCallExpression = new CodeMethodInvokeExpression(); 
                                methCallExpression.Method.TargetObject = new CodeThisReferenceExpression();
                                methCallExpression.Method.MethodName = "CreateResourceBasedLiteralControl";
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(offset));
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(size)); 
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(fAsciiOnly));
                                expr = methCallExpression; 
                            } 

                            BuildAddParsedSubObjectStatement(buildSubControlBlock, expr, linePragma, ctrlRefExpr, ref gotParserVariable); 
                        }
                    }
                }
            } 

            // Process the complex attributes 
            if (builder.ComplexPropertyEntries.Count > 0) { 

                // Used to deal with the device filter conditionals 
                CodeStatementCollection currentStmts;
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null;
                int localVarIndex = 1; 
                String localVariableRef = null;
 
                foreach (ComplexPropertyEntry pseSub in builder.ComplexPropertyEntries) { 

                    currentStmts = nextStmts; 

                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts);

                    if (pseSub.Builder is StringPropertyBuilder) { 
                        // If it's a string inner property, treat it like a simple property
                        CodeExpression leftExpr, rightExpr = null; 
 
                        // __ctrl.{{_name}}
                        // In case of a string property, there should only be one property name (unlike complex properties) 
                        Debug.Assert(pseSub.Name.IndexOf('.') < 0, "pseSub._name.IndexOf('.') < 0");
                        leftExpr = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);

                        // We need to call BuildStringPropertyExpression so any additional processing can be done 
                        rightExpr = BuildStringPropertyExpression(pseSub);
 
                        // Now that we have both side, add the assignment 
                        CodeAssignStatement setStatment = new CodeAssignStatement(leftExpr, rightExpr);
                        setStatment.LinePragma = linePragma; 
                        currentStmts.Add(setStatment);

                        continue;
                    } 

                    if (pseSub.ReadOnly) { 
 
                        if (fControlSkin && pseSub.Builder != null && pseSub.Builder is CollectionBuilder &&
                        pseSub.Builder.ComplexPropertyEntries.Count > 0) { 

                            // If it's a collection on a control theme and the themed collection is not empty, clear it first.
                            // e.g. __ctrl.{{pse_name}}.Clear();
 
                            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
                            // Look for the "Clear" method on the collection. 
                            if (pseSub.Type.GetMethod("Clear", bindingFlags) != null) { 
                                CodeMethodReferenceExpression refExpr = new CodeMethodReferenceExpression();
                                refExpr.MethodName = "Clear"; 
                                refExpr.TargetObject = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);
                                CodeMethodInvokeExpression invokeClearExpr = new CodeMethodInvokeExpression();
                                invokeClearExpr.Method = refExpr;
                                currentStmts.Add(invokeClearExpr); 
                            }
                        } 
 
                        // If it's a readonly prop, pass it as a parameter to the
                        // build method. 
                        // e.g. __BuildControl {{controlName}}(__ctrl.{{pse._name}});
                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + pseSub.Builder.ID);
                        methCallExpression.Parameters.Add(new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name)); 
                        methCallStatement = new CodeExpressionStatement(methCallExpression);
                        methCallStatement.LinePragma = linePragma; 
                        currentStmts.Add(methCallStatement); 
                    }
                    else { 
                        localVariableRef = _localVariableRef + (localVarIndex++).ToString(CultureInfo.InvariantCulture);

                        // e.g. {{controlTypeName}} ctrl4;
                        CodeTypeReference ctrlTypeReference = 
                            new CodeTypeReference(pseSub.Builder.ControlType, CodeTypeReferenceOptions.GlobalReference);
                        currentStmts.Add(new CodeVariableDeclarationStatement(ctrlTypeReference, localVariableRef)); 
 
                        // Variable reference to the local control variable.
                        CodeVariableReferenceExpression childCtrlRefExpr = new CodeVariableReferenceExpression(localVariableRef); 

                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + pseSub.Builder.ID);
                        methCallStatement = new CodeExpressionStatement(methCallExpression); 

                        // e.g. ctrl4 = __BuildControl {{controlName}}(); 
                        CodeAssignStatement setCtl = new CodeAssignStatement(childCtrlRefExpr, methCallExpression); 
                        setCtl.LinePragma = linePragma;
                        currentStmts.Add(setCtl); 

                        if (pseSub.IsCollectionItem) {
                            // e.g. __ctrl.Add(ctrl4);
                            methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "Add"); 
                            methCallStatement = new CodeExpressionStatement(methCallExpression);
                            methCallStatement.LinePragma = linePragma; 
                            currentStmts.Add(methCallStatement); 
                            methCallExpression.Parameters.Add(childCtrlRefExpr);
                        } 
                        else {
                            // e.g. __ctrl.{{pse._name}} = {{controlName}};
                            CodeAssignStatement set = new CodeAssignStatement();
                            set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name); 
                            set.Right = childCtrlRefExpr;
                            set.LinePragma = linePragma; 
                            currentStmts.Add(set); 
                        }
                    } 
                }
            }

            // If there are bound properties, hook up the binding method 
            if (builder.BoundPropertyEntries.Count > 0) {
 
                bool isBindableTemplateBuilder = builder is BindableTemplateBuilder; 
                bool hasDataBindingEntry = false;
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts;
                CodeStatementCollection methodStatements = statements;
                CodeStatementCollection nextStmts = statements; 
                PropertyEntry previous = null;
 
                bool hasTempObject = false; 

                foreach (BoundPropertyEntry entry in builder.BoundPropertyEntries) { 

                    // Skip two-way entries if it's a BindableTemplateBuilder or the two-way entry has no setter
                    if (entry.TwoWayBound && (isBindableTemplateBuilder || entry.ReadOnlyProperty))
                        continue; 

                    if (entry.IsDataBindingEntry) { 
                        hasDataBindingEntry = true; 
                        continue;
                    } 

                    currentStmts = nextStmts;

                    HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStmts, out nextStmts); 

                    ExpressionBuilder eb = entry.ExpressionBuilder; 
                    Debug.Assert(eb != null, "Did not expect null expression builder"); 
                    eb.BuildExpression(entry, builder, ctrlRefExpr, methodStatements, currentStmts, null, ref hasTempObject);
                } 

                if (hasDataBindingEntry) {

                    EventInfo eventInfo = DataBindingExpressionBuilder.Event; 

                    // __ctrl.{EventName} += new EventHandler(this.{{bindingMethod}}) 
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression(); 
                    CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, eventInfo.Name, newDelegate);
                    attachEvent.LinePragma = linePragma; 
                    newDelegate.DelegateType = new CodeTypeReference(typeof(EventHandler));
                    newDelegate.TargetObject = new CodeThisReferenceExpression();
                    newDelegate.MethodName = GetExpressionBuilderMethodName(eventInfo.Name, builder);
                    statements.Add(attachEvent); 
                }
            } 
 
            if (builder is DataBoundLiteralControlBuilder) {
 
                // __ctrl.DataBinding += new EventHandler(this.{{bindingMethod}})
                CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, "DataBinding", newDelegate);
                attachEvent.LinePragma = linePragma; 
                newDelegate.DelegateType = new CodeTypeReference(typeof(EventHandler));
                newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                newDelegate.MethodName = BindingMethodName(builder); 
                statements.Add(attachEvent);
            } 

            // If there is any ASP code, set the render method delegate
            if (builder.HasAspCode && !fControlSkin) {
                // e.g. __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render {{controlName}})); 
                CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                newDelegate.DelegateType = new CodeTypeReference(typeof(RenderMethod)); 
                newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                newDelegate.MethodName = "__Render" + builder.ID;
 
                methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "SetRenderMethodDelegate");
                methCallExpression.Parameters.Add(newDelegate);
                methCallStatement = new CodeExpressionStatement(methCallExpression);
 
                // VSWhidbey 579101
                // If this is a contentPlaceHolder, we need to check if there is any content defined. 
                // We set the render method only when there is no contentTemplate defined. 
                // if ((this.__Template_TestTemplate == null)) {
                //     __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render {{controlName}})); 
                // }
                if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) {
                    string templateName = ((System.Web.UI.WebControls.ContentPlaceHolderBuilder)builder).Name;
                    autoTemplateName = MasterPageControlBuilder.AutoTemplatePrefix + templateName; 
                    string fieldName = "__" + autoTemplateName;
                    CodeExpression templateFieldRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName); 
                    templateIfStmt = new CodeConditionStatement(); 
                    templateIfStmt.Condition = new CodeBinaryOperatorExpression(templateFieldRef, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null));
                    templateIfStmt.TrueStatements.Add(methCallStatement); 
                    statements.Add(templateIfStmt);
                }
                else {
                    statements.Add(methCallStatement); 
                }
            } 
 
            // Process the events
            if (builder.EventEntries.Count > 0) { 

                foreach (EventEntry eventEntry in builder.EventEntries) {

                    // Attach the event.  Detach it first to avoid duplicates (see ASURT 42603), 
                    // but only if there is codebehind
                    // 
 

                    // e.g. __ctrl.ServerClick -= new System.EventHandler(this.buttonClicked); 
                    // e.g. __ctrl.ServerClick += new System.EventHandler(this.buttonClicked);
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                    newDelegate.DelegateType = new CodeTypeReference(eventEntry.HandlerType);
                    newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                    newDelegate.MethodName = eventEntry.HandlerMethodName;
 
                    if (Parser.HasCodeBehind) { 
                        CodeRemoveEventStatement detachEvent = new CodeRemoveEventStatement(ctrlRefExpr, eventEntry.Name, newDelegate);
                        detachEvent.LinePragma = linePragma; 
                        statements.Add(detachEvent);
                    }

                    CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, eventEntry.Name, newDelegate); 
                    attachEvent.LinePragma = linePragma;
                    statements.Add(attachEvent); 
                } 
            }
 
            // If a control field is declared, we need to return it at the end of the method.
            if (fControlFieldDeclared)
                statements.Add(new CodeMethodReturnStatement(ctrlRefExpr));
        } 

        /* 
         * Build the template's method to extract values from contained controls 
         */
        protected void BuildExtractMethod(ControlBuilder builder) { 
            BindableTemplateBuilder bindableTemplateBuilder = builder as BindableTemplateBuilder;
            // This will get called if Bind is in a non-bindable template.  We should just skip the Extract method.
            if (bindableTemplateBuilder != null && bindableTemplateBuilder.HasTwoWayBoundProperties) {
                // Get the name of the databinding method 
                string methodName = ExtractMethodName(builder);
                const string tableVarName = "__table"; 
                const string containerVarName = "__container"; 

                // Same linePragma in the entire method 
                CodeLinePragma linePragma = CreateCodeLinePragma(builder);

                CodeMemberMethod method = new CodeMemberMethod();
                AddDebuggerNonUserCodeAttribute(method); 
                method.Name = methodName;
                method.Attributes &= ~MemberAttributes.AccessMask; 
                method.Attributes |= MemberAttributes.Public; 
                method.ReturnType = new CodeTypeReference(typeof(IOrderedDictionary));
                _sourceDataClass.Members.Add(method); 

                /// Variable declarations need to go at the top for CodeDom compliance.
                CodeStatementCollection topLevelStatements = method.Statements;
                CodeStatementCollection statements = new CodeStatementCollection(); 

                // add a container control parameter 
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control), containerVarName)); 

                // OrderedDictionary table; 
                CodeVariableDeclarationStatement tableDecl = new CodeVariableDeclarationStatement(typeof(OrderedDictionary), tableVarName);
                topLevelStatements.Add(tableDecl);

                // table = new OrderedDictionary(); 
                CodeObjectCreateExpression newTableExpression = new CodeObjectCreateExpression(typeof(OrderedDictionary));
                CodeAssignStatement newTableAssign = new CodeAssignStatement(new CodeVariableReferenceExpression(tableVarName), 
                                                                             newTableExpression); 
                newTableAssign.LinePragma = linePragma;
                statements.Add(newTableAssign); 

                BuildExtractStatementsRecursive(bindableTemplateBuilder.SubBuilders, statements, topLevelStatements, linePragma, tableVarName, containerVarName);

                // return table; 
                CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(new CodeVariableReferenceExpression(tableVarName));
                statements.Add(returnStatement); 
 
                // add all the non-variable declaration statements to the bottom of the method
                method.Statements.AddRange(statements); 
            }
        }

        private void BuildExtractStatementsRecursive(ArrayList subBuilders, CodeStatementCollection statements, CodeStatementCollection topLevelStatements, CodeLinePragma linePragma, string tableVarName, string containerVarName) { 
            foreach (object subBuilderObject in subBuilders) {
                ControlBuilder controlBuilder = subBuilderObject as ControlBuilder; 
                if (controlBuilder != null) { 
                    // Used to deal with the device filter conditionals
                    CodeStatementCollection currentStatements = null; 
                    CodeStatementCollection nextStatements = statements;
                    PropertyEntry previous = null;
                    string previousControlName = null;
                    bool newControl = true; 

                    foreach (BoundPropertyEntry entry in controlBuilder.BoundPropertyEntries) { 
 
                        // Skip all entries that are not two-way
                        if (!entry.TwoWayBound) 
                            continue;

                        // Reset the "previous" Property Entry if we're not looking at the same control.
                        // If we don't do this, Two controls that have conditionals on the same named property will have 
                        // their conditionals incorrectly merged.
                        if (String.Compare(previousControlName, entry.ControlID, StringComparison.Ordinal) != 0) { 
                            previous = null; 
                            newControl = true;
                        } 
                        else {
                            newControl = false;
                        }
 
                        previousControlName = entry.ControlID;
                        currentStatements = nextStatements; 
 
                        HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStatements, out nextStatements);
 
                        // Only declare the variable if it hasn't already been declared by a previous filter
                        // or property binding on the same control.
                        if (newControl) {
                            // {{controlType}} {{controlID}}; 
                            // eg. TextBox t1;
                            CodeVariableDeclarationStatement controlDecl = new CodeVariableDeclarationStatement(entry.ControlType, entry.ControlID); 
                            topLevelStatements.Add(controlDecl); 

                            // {{controlID}} = ({{controlType}})container.FindControl("{{controlID}}"); 
                            // eg. t1 = (TextBox)container.FindControl("t1");
                            CodeMethodInvokeExpression findControlCallExpression = new CodeMethodInvokeExpression(
                                    new CodeVariableReferenceExpression(containerVarName), "FindControl");
                            string findControlParameter = entry.ControlID; 
                            findControlCallExpression.Parameters.Add(new CodePrimitiveExpression(findControlParameter));
                            CodeCastExpression castExpression = new CodeCastExpression(entry.ControlType, findControlCallExpression); 
 
                            CodeAssignStatement findControlAssign = new CodeAssignStatement(new CodeVariableReferenceExpression(entry.ControlID),
                                                                                            castExpression); 
                            findControlAssign.LinePragma = linePragma;
                            topLevelStatements.Add(findControlAssign);
                        }
 
                        // if ({{controlID}} != null)
                        //     table["{{fieldName}}"] = {{controlID}}.{{propertyName}}); 
                        // eg. if (t1 != null) 
                        // eg.     table["field"] = t1.Text);
                        CodeConditionStatement ifStatement = new CodeConditionStatement(); 
                        CodeBinaryOperatorExpression ensureControlExpression = new CodeBinaryOperatorExpression();
                        ensureControlExpression.Operator = CodeBinaryOperatorType.IdentityInequality;
                        ensureControlExpression.Left = new CodeVariableReferenceExpression(entry.ControlID);
                        ensureControlExpression.Right = new CodePrimitiveExpression(null); 
                        ifStatement.Condition = ensureControlExpression;
 
                        string fieldParameter = entry.FieldName; 
                        CodeIndexerExpression tableIndexer = new CodeIndexerExpression(new CodeVariableReferenceExpression(tableVarName),
                                                                                       new CodePrimitiveExpression(fieldParameter)); 

                        // VJ# does not support automatic boxing of value types, so passing a simple type, say a bool, into a method
                        // expecting an object will give a compiler error.  We are working around this issue by adding special code for
                        // VJ# that will cast the expression for boxing.  When the VJ# team adds implicit boxing of value types, we 
                        // should remove this code.  VSWhidbey 269028
                        CodeExpression controlPropertyExpression = CodeDomUtility.BuildPropertyReferenceExpression(new CodeVariableReferenceExpression(entry.ControlID), entry.Name); 
                        if (_usingVJSCompiler) { 
                            controlPropertyExpression = CodeDomUtility.BuildJSharpCastExpression(entry.Type, controlPropertyExpression);
                        } 
                        CodeAssignStatement tableIndexAssign = new CodeAssignStatement(tableIndexer, controlPropertyExpression);

                        ifStatement.TrueStatements.Add(tableIndexAssign);
                        ifStatement.LinePragma = linePragma; 
                        currentStatements.Add(ifStatement);
                    } 
 
                    if (controlBuilder.SubBuilders.Count > 0) {
                        BuildExtractStatementsRecursive(controlBuilder.SubBuilders, statements, topLevelStatements, linePragma, tableVarName, containerVarName); 
                    }
                }
            }
 
        }
 
        /* 
         * Build the member field's declaration for a control
         */ 
        private void BuildFieldDeclaration(ControlBuilder builder) {

            // Do not generate member field for content controls.
            if (builder is System.Web.UI.WebControls.ContentBuilderInternal) { 
                return;
            } 
 
            bool hideExistingMember = false;
 
            // If we're using a non-default base class
            if (Parser.BaseType != null) {
                // Check if it has a non-private field or property that has a name that
                // matches the id of the control. 

                Type memberType = Util.GetNonPrivateFieldType(Parser.BaseType, builder.ID); 
 
                // Couldn't find a field, try a property (ASURT 45039)
                // 
                if (memberType == null)
                    memberType = Util.GetNonPrivatePropertyType(Parser.BaseType, builder.ID);

                if (memberType != null) { 

                    if (!memberType.IsAssignableFrom(builder.ControlType)) { 
 
                        if (!(typeof(Control)).IsAssignableFrom(memberType)) {
                            // If it's not a control, it's probably an unrelated member, 
                            // and we should just hide it (VSWhidbey 217135)
                            hideExistingMember = true;
                        }
                        else { 
                            throw new HttpParseException(SR.GetString(SR.Base_class_field_with_type_different_from_type_of_control,
                                builder.ID, memberType.FullName, builder.ControlType.FullName), null, 
                                builder.VirtualPath, null, builder.Line); 
                        }
                    } 
                    else {
                        // Don't build the declaration, since the base class already declares it
                        return;
                    } 
                }
            } 
 
            // Add the field.  Make it protected if the ID was declared, and private if it was generated
            CodeMemberField field = new CodeMemberField(new CodeTypeReference( 
                builder.DeclareType, CodeTypeReferenceOptions.GlobalReference), builder.ID);
            field.Attributes &= ~MemberAttributes.AccessMask;

            // If we need to hide an existing member, use 'new' (VSWhidbey 217135) 
            if (hideExistingMember)
                field.Attributes |= MemberAttributes.New; 
 
            field.LinePragma = CreateCodeLinePragma(builder);
 
            field.Attributes |= MemberAttributes.Family;

            // Set WithEvents in the UserData, so that the field will be
            // declared as WithEvents in VB (VSWhidbey 156623). 
            // But only do this if it's a Control, otherwise it may not have
            // any events (VSWhidbey 283274). 
            if (typeof(Control).IsAssignableFrom(builder.DeclareType)) { 
                field.UserData["WithEvents"] = true;
            } 

            _intermediateClass.Members.Add(field);
        }
 
        private string GetExpressionBuilderMethodName(string eventName, ControlBuilder builder) {
            return "__" + eventName + builder.ID; 
        } 

        /* 
         * Return the name of a databinding method
         */
        private string BindingMethodName(ControlBuilder builder) {
            return "__DataBind" + builder.ID; 
        }
 
        protected CodeMemberMethod BuildPropertyBindingMethod(ControlBuilder builder, bool fControlSkin) { 
            if (builder is DataBoundLiteralControlBuilder) {
                // Get the name of the databinding method 
                string methodName = BindingMethodName(builder);

                // Same linePragma in the entire method
                CodeLinePragma linePragma = CreateCodeLinePragma(builder); 

                CodeMemberMethod method = new CodeMemberMethod(); 
                method.Name = methodName; 
                method.Attributes &= ~MemberAttributes.AccessMask;
                method.Attributes |= MemberAttributes.Public; 

                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "sender"));
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(EventArgs), "e"));
 
                CodeStatementCollection topMethodStatements = new CodeStatementCollection();
                CodeStatementCollection otherMethodStatements = new CodeStatementCollection(); 
 
                // {{controlType}} target;
                CodeVariableDeclarationStatement targetDecl = new CodeVariableDeclarationStatement(builder.ControlType, "target"); 
                Type bindingContainerType = builder.BindingContainerType;

                CodeVariableDeclarationStatement containerDecl = new CodeVariableDeclarationStatement(bindingContainerType, "Container");
 
                topMethodStatements.Add(containerDecl);
                topMethodStatements.Add(targetDecl); 
 
                // target = ({{controlType}}) sender;
                CodeAssignStatement setTarget = new CodeAssignStatement(new CodeVariableReferenceExpression(targetDecl.Name), 
                                                                        new CodeCastExpression(builder.ControlType,
                                                                                               new CodeArgumentReferenceExpression("sender")));
                setTarget.LinePragma = linePragma;
                otherMethodStatements.Add(setTarget); 

                // {{containerType}} Container = ({{containerType}}) target.BindingContainer; 
                CodeAssignStatement setContainer = new CodeAssignStatement(new CodeVariableReferenceExpression(containerDecl.Name), 
                                                                           new CodeCastExpression(bindingContainerType,
                                                                                                  new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("target"), 
                                                                                                                                      "BindingContainer")));
                setContainer.LinePragma = linePragma;
                otherMethodStatements.Add(setContainer);
 
                // VSWhidbey 275175: Create the tempObjectVariable "__o" only when it's used.
                bool tempObjectVariableDeclared = false; 
 
                // If it's a DataBoundLiteralControl, call SetDataBoundString for each
                // of the databinding expressions 
                int i = -1;
                foreach (object child in builder.SubBuilders) {
                    i++;
 
                    // Ignore it if it's null
                    if (child == null) 
                        continue; 

                    // Only deal with the databinding expressions here, which have odd index 
                    if (i % 2 == 0) {
                        Debug.Assert(child is string, "child is string");
                        continue;
                    } 

                    CodeBlockBuilder codeBlock = (CodeBlockBuilder) child; 
                    Debug.Assert(codeBlock.BlockType == CodeBlockType.DataBinding); 

                    // In designer mode, generate a much simpler assignment to make 
                    // the code simpler (since it doesn't actually need to run).
                    if (_designerMode) {

                        // In designer mode, add an object variable used for simplified code expression generation 
                        if (!tempObjectVariableDeclared) {
                            tempObjectVariableDeclared = true; 
                            // object __o; 
                            topMethodStatements.Add(new CodeVariableDeclarationStatement(
                                typeof(object), tempObjectVariable)); 
                        }

                        // e.g. __o = ;
                        CodeStatement simpleAssignment = new CodeAssignStatement( 
                            new CodeVariableReferenceExpression(tempObjectVariable),
                            new CodeSnippetExpression(codeBlock.Content)); 
                        simpleAssignment.LinePragma = CreateCodeLinePragma(codeBlock); 
                        otherMethodStatements.Add(simpleAssignment);
                        continue; 
                    }

                    // e.g. target.SetDataBoundString(3, System.Convert.ToString({{codeExpr}}));
                    CodeExpression convertExpr = CodeDomUtility.GenerateConvertToString( 
                        new CodeSnippetExpression(codeBlock.Content.Trim()));
 
                    CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression( 
                        new CodeVariableReferenceExpression("target"), "SetDataBoundString");
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(i/2)); 
                    methCallExpression.Parameters.Add(convertExpr);

                    CodeStatement setDataBoundStringCall = new CodeExpressionStatement(methCallExpression);
                    setDataBoundStringCall.LinePragma = CreateCodeLinePragma(codeBlock); 
                    otherMethodStatements.Add(setDataBoundStringCall);
                } 
 
                foreach (CodeStatement stmt in topMethodStatements) {
                    method.Statements.Add(stmt); 
                }
                foreach (CodeStatement stmt in otherMethodStatements) {
                    method.Statements.Add(stmt);
                } 
                _sourceDataClass.Members.Add(method);
                return method; 
            } 
            else {
 
                EventInfo eventInfo = DataBindingExpressionBuilder.Event;

                // Same linePragma in the entire method
                CodeLinePragma linePragma = CreateCodeLinePragma(builder); 

                CodeMemberMethod method = null; 
                CodeStatementCollection topStatements = null; 
                CodeStatementCollection otherStatements = null;
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts;
                CodeStatementCollection nextStmts = null;
                PropertyEntry previous = null; 

                bool isBindableTemplateBuilder = builder is BindableTemplateBuilder; 
                bool firstEntry = true; 

                bool hasTempObject = false; 

                foreach (BoundPropertyEntry entry in builder.BoundPropertyEntries) {
                    // Skip two-way entries if it's a BindableTemplateBuilder or the two way entry is read only
                    if (entry.TwoWayBound && (isBindableTemplateBuilder || entry.ReadOnlyProperty)) 
                        continue;
 
                    // We only care about databinding entries here 
                    if (!entry.IsDataBindingEntry)
                        continue; 

                    if (firstEntry) {
                        firstEntry = false;
 
                        method = new CodeMemberMethod();
                        topStatements = new CodeStatementCollection(); 
                        otherStatements = new CodeStatementCollection(); 

                        // Get the name of the databinding method 
                        string methodName = GetExpressionBuilderMethodName(eventInfo.Name, builder);
                        method.Name = methodName;
                        method.Attributes &= ~MemberAttributes.AccessMask;
                        method.Attributes |= MemberAttributes.Public; 

                        if (_designerMode) { 
                            ApplyEditorBrowsableCustomAttribute(method); 
                        }
 
                        Type eventHandlerType = eventInfo.EventHandlerType;
                        MethodInfo mi = eventHandlerType.GetMethod("Invoke");
                        ParameterInfo[] paramInfos = mi.GetParameters();
                        foreach (ParameterInfo pi in paramInfos) { 
                            method.Parameters.Add(new CodeParameterDeclarationExpression(pi.ParameterType, pi.Name));
                        } 
 
                        nextStmts = otherStatements;
 
                        DataBindingExpressionBuilder.BuildExpressionSetup(builder, topStatements, otherStatements);

                        _sourceDataClass.Members.Add(method);
                    } 

                    currentStmts = nextStmts; 
 
                    HandleDeviceFilterConditional(ref previous, entry, otherStatements, ref currentStmts, out nextStmts);
 
                    if (entry.TwoWayBound) {
                        Debug.Assert(!entry.ReadOnlyProperty, "We should not attempt to build a data binding handler if the two way entry is read only.");
                        Debug.Assert(!entry.UseSetAttribute, "Two-way binding is not supported on expandos - this should have been prevented in ControlBuilder");
                        DataBindingExpressionBuilder.BuildEvalExpression(entry.FieldName, entry.FormatString, 
                                                                         entry.Name, entry.Type, builder, topStatements, currentStmts, linePragma, ref hasTempObject);
                    } 
                    else { 
                        DataBindingExpressionBuilder.BuildExpressionStatic(entry, builder, null, topStatements, currentStmts, linePragma, ref hasTempObject);
                    } 
                }
                if (topStatements != null) {
                    foreach (CodeStatement stmt in topStatements) {
                        method.Statements.Add(stmt); 
                    }
                } 
                if (otherStatements != null) { 
                    foreach (CodeStatement stmt in otherStatements) {
                        method.Statements.Add(stmt); 
                    }
                }
                return method;
            } 
        }
 
        /* 
         * Build the data tree for a control's render method
         */ 
        internal void BuildRenderMethod(ControlBuilder builder, bool fTemplate) {

            CodeMemberMethod method = new CodeMemberMethod();
            method.Attributes = MemberAttributes.Private | MemberAttributes.Final; 
            method.Name = "__Render" + builder.ID;
 
            if (_designerMode) { 
                ApplyEditorBrowsableCustomAttribute(method);
            } 

            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(HtmlTextWriter), renderMethodParameterName));
            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control), "parameterContainer"));
 
            _sourceDataClass.Members.Add(method);
 
            // VSWhidbey 275175: Create the tempObjectVariable "__o" only when it's used. 
            bool tempObjectVariableDeclared = false;
 
            // Process the children if any
            if (builder.SubBuilders != null) {
                IEnumerator en = builder.SubBuilders.GetEnumerator();
 
                // Index that the control will have in its parent's Controls
                // collection. 
                // 

 

                int controlIndex = 0;

                for (int i=0; en.MoveNext(); i++) { 
                    object child = en.Current;
 
                    CodeLinePragma linePragma = null; 

                    if (child is ControlBuilder) { 
                        linePragma = CreateCodeLinePragma((ControlBuilder)child);
                    }

                    if (child is string) { 
                        if (_designerMode) continue;
 
                        AddOutputWriteStringStatement(method.Statements, (string)child); 
                    }
                    else if (child is CodeBlockBuilder) { 
                        CodeBlockBuilder codeBlockBuilder = (CodeBlockBuilder)child;

                        if (codeBlockBuilder.BlockType == CodeBlockType.Expression) {
 
                            string codeExpression = codeBlockBuilder.Content;
 
                            // In designer mode, generate a much simpler assignment to make 
                            // the code simpler (since it doesn't actually need to run).
                            if (_designerMode) { 
                                // In designer mode, add an object variable used for simplified code expression generation
                                if (!tempObjectVariableDeclared) {
                                    tempObjectVariableDeclared = true;
                                    // object __o; 
                                    method.Statements.Add(new CodeVariableDeclarationStatement(
                                        typeof(object), tempObjectVariable)); 
                                } 

                                // e.g. __o = ; 
                                CodeStatement simpleAssignment = new CodeAssignStatement(
                                    new CodeVariableReferenceExpression(tempObjectVariable),
                                    new CodeSnippetExpression(codeExpression));
                                simpleAssignment.LinePragma = linePragma; 
                                method.Statements.Add(simpleAssignment);
                                continue; 
                            } 

                            // The purpose of the following logic is to improve the debugging experience. 
                            // Basically, we gain control on the formatting of the generated line
                            // that calls output.Write, in order to try to make the call line up
                            // with the <%= ... %> block.  It's not always perfect, but it does a decent job
                            // and is always better than the v1 behavior. 

                            // Get the Write() statement codedom tree 
                            CodeStatement outputWrite = GetOutputWriteStatement( 
                                new CodeSnippetExpression(codeExpression));
 
                            // Use codedom to generate the statement as a string in the target language
                            TextWriter w = new StringWriter(CultureInfo.InvariantCulture);
                            _codeDomProvider.GenerateCodeFromStatement(outputWrite, w, null /*CodeGeneratorOptions*/);
                            string outputWriteString = w.ToString(); 

                            // The '+3' is used to make sure the generated code is positioned properly to match 
                            // the location of user code (due to the <%= %> separators). 
                            outputWriteString = outputWriteString.PadLeft(
                                codeBlockBuilder.Column + codeExpression.Length + 3); 

                            // We can then use this string as a snippet statement
                            CodeSnippetStatement lit = new CodeSnippetStatement(outputWriteString);
                            lit.LinePragma = linePragma; 
                            method.Statements.Add(lit);
                        } 
                        else { 
                            // It's a <% ... %> block
                            Debug.Assert(codeBlockBuilder.BlockType == CodeBlockType.Code); 

                            // Pad the code block so its generated offset matches the aspx
                            string code = codeBlockBuilder.Content;
                            code = code.PadLeft(code.Length + codeBlockBuilder.Column - 1); 

                            CodeSnippetStatement lit = new CodeSnippetStatement(code); 
                            lit.LinePragma = linePragma; 
                            method.Statements.Add(lit);
                        } 
                    }
                    else if (child is ControlBuilder) {

                        if (_designerMode) continue; 

                        // parameterContainer.Controls['controlIndex++'].RenderControl(output) 
                        CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); 
                        CodeExpressionStatement methodCall = new CodeExpressionStatement(methodInvoke);
                        methodInvoke.Method.TargetObject = new CodeIndexerExpression(new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression("parameterContainer"), 
                                                                                                                             "Controls"),
                                                                                         new CodeExpression[] {
                                                                                             new CodePrimitiveExpression(controlIndex++),
                                                                                         }); 
                        methodInvoke.Method.MethodName = "RenderControl";
 
                        // Don't generate a line pragma on the RenderControl call, as it degrades the 
                        // debugging experience (VSWhidbey 482416)
 
                        methodInvoke.Parameters.Add(new CodeArgumentReferenceExpression(renderMethodParameterName));
                        method.Statements.Add(methodCall);
                    }
                } 
            }
        } 
 
        protected virtual void BuildSourceDataTreeFromBuilder(ControlBuilder builder,
                                                    bool fInTemplate, bool topLevelControlInTemplate, 
                                                    PropertyEntry pse) {

            // Don't do anything for Code blocks
            if (builder is CodeBlockBuilder) 
                return;
 
            // Is the current builder for a template? 
            bool fTemplate = (builder is TemplateBuilder);
 
            // For the control name in the compiled code, we use the
            // ID if one is available (but don't use the ID inside a template)
            // Otherwise, we generate a unique name.
            if (builder.ID == null || fInTemplate) { 
                // Increase the control count to generate unique ID's
                _controlCount++; 
 
                builder.ID = "__control" + _controlCount.ToString(NumberFormatInfo.InvariantInfo);
                builder.IsGeneratedID = true; 
            }

            // Process the children
            if (builder.SubBuilders != null) { 
                foreach (object child in builder.SubBuilders) {
                    if (child is ControlBuilder) { 
                        // Do not treat it as top level control in template if the control is at top-level of a file. 
                        bool isTopLevelCtrlInTemplate =
                            fTemplate && typeof(Control).IsAssignableFrom(((ControlBuilder)child).ControlType) && !(builder is RootBuilder); 
                        BuildSourceDataTreeFromBuilder((ControlBuilder)child, fInTemplate, isTopLevelCtrlInTemplate, null);
                    }
                }
            } 

            foreach (TemplatePropertyEntry entry in builder.TemplatePropertyEntries) { 
                bool inTemplate = true; 

                // If the template container does not allow multiple instances, 
                // treat the controls as if not in templates.
                if (entry.PropertyInfo != null) {
                    TemplateInstanceAttribute templateAttrib = (TemplateInstanceAttribute)Attribute.GetCustomAttribute(entry.PropertyInfo,
                        typeof(TemplateInstanceAttribute), false /* inherit */); 
                    if (templateAttrib != null) {
                        inTemplate = (templateAttrib.Instances == TemplateInstance.Multiple); 
                    } 
                }
 
                BuildSourceDataTreeFromBuilder(((TemplatePropertyEntry)entry).Builder, inTemplate, false /*topLevelControlInTemplate*/, entry);
            }

            foreach (ComplexPropertyEntry entry in builder.ComplexPropertyEntries) { 
                // Don't create a build method for inner property strings
                if (!(entry.Builder is StringPropertyBuilder)) { 
                    BuildSourceDataTreeFromBuilder(((ComplexPropertyEntry)entry).Builder, fInTemplate, false /*topLevelControlInTemplate*/, entry); 
                }
            } 

            // Build a field declaration for the control if ID is defined on the control.
            // (Not a generated ID)
            if (!builder.IsGeneratedID) 
                BuildFieldDeclaration(builder);
 
            CodeMemberMethod buildMethod = null; 
            CodeMemberMethod dataBindingMethod = null;
 
            // Skip the rest if we're only generating the intermediate class
            if (_sourceDataClass != null) {

                if (!_designerMode) { 
                    // Build a Build method for the control
                    buildMethod = BuildBuildMethod(builder, fTemplate, fInTemplate, topLevelControlInTemplate, pse, false); 
                } 

                // Build a Render method for the control, unless it has no code 
                if (builder.HasAspCode) {
                    BuildRenderMethod(builder, fTemplate);
                }
 
                // Build a method to extract values from the template
                BuildExtractMethod(builder); 
 
                // Build a property binding method for the control
                dataBindingMethod = BuildPropertyBindingMethod(builder, false); 
            }

            // Give the ControlBuilder a chance to look at and modify the tree
            builder.ProcessGeneratedCode(_codeCompileUnit, _intermediateClass, 
                _sourceDataClass, buildMethod, dataBindingMethod);
        } 
 
        internal virtual CodeExpression BuildStringPropertyExpression(PropertyEntry pse) {
            string value = String.Empty; 
            if (pse is SimplePropertyEntry) {
                value = (string)((SimplePropertyEntry)pse).Value;
            }
            else { 
                Debug.Assert(pse is ComplexPropertyEntry);
                ComplexPropertyEntry cpe = (ComplexPropertyEntry)pse; 
                value = (string)((StringPropertyBuilder)cpe.Builder).BuildObject(); 
            }
 
            return CodeDomUtility.GenerateExpressionForValue(pse.PropertyInfo, value, typeof(string));
        }

        protected virtual CodeAssignStatement BuildTemplatePropertyStatement(CodeExpression ctrlRefExpr) { 

            // e.g. __ctrl.TemplateControl = this; 
            CodeAssignStatement assign = new CodeAssignStatement(); 
            assign.Left = new CodePropertyReferenceExpression(ctrlRefExpr, "TemplateControl");
            assign.Right = new CodeThisReferenceExpression(); 
            return assign;
        }

        /* 
         * Return the name of an extract method
         */ 
        private string ExtractMethodName(ControlBuilder builder) { 
            return extractTemplateValuesMethodPrefix + builder.ID;
        } 


        private Type GetCtrlTypeForBuilder(ControlBuilder builder, bool fTemplate) {
 
            if (builder is RootBuilder && builder.ControlType != null)
                return builder.ControlType; 
 
            if (fTemplate)
                return typeof(Control); 

            return builder.ControlType;
        }
 
        protected string GetMethodNameForBuilder(string prefix, ControlBuilder builder) {
            if (builder is RootBuilder) { 
                return prefix + "Tree"; 
            }
            else { 
                return prefix + builder.ID;
            }
        }
 
        /*
         * Helper method to generate the device filter conditionals.  e.g. 
         *   if (this.TestDeviceFilter("FilterName")) { 
         *       // ...
         *   } 
         *   else {
         *       // ...
         *   }
         */ 
        private void HandleDeviceFilterConditional(
            ref PropertyEntry previous, PropertyEntry current, 
            CodeStatementCollection topStmts, 
            ref CodeStatementCollection currentStmts,
            out CodeStatementCollection nextStmts) { 

            bool sameAsPrevious = (previous != null) && StringUtil.EqualsIgnoreCase(previous.Name, current.Name);

            if (current.Filter.Length != 0) { 
                if (!sameAsPrevious) {
                    // If the current property entry is not the same as the previous entries, 
                    // we need to start a new block of code 
                    currentStmts = topStmts;
                    previous = null; 
                }

                CodeConditionStatement ifStmt = new CodeConditionStatement();
                CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression( 
                    new CodeThisReferenceExpression(), "TestDeviceFilter");
                methCallExpression.Parameters.Add(new CodePrimitiveExpression(current.Filter)); 
                ifStmt.Condition = methCallExpression; 
                currentStmts.Add(ifStmt);
 
                // The current entry needs to go in the 'if' clause
                currentStmts = ifStmt.TrueStatements;

                // The next entry will tentatively go in the 'else' clause, unless it is 
                // for a different property (which we would catch next time around)
                nextStmts = ifStmt.FalseStatements; 
 
                previous = current;
            } 
            else {
                // If we're switching to a new property, we need to add to the top-level statements (not the false block of an if)
                if (!sameAsPrevious) {
                    currentStmts = topStmts; 
                }
                nextStmts = topStmts; 
                previous = null; 
            }
        } 

        protected virtual bool UseResourceLiteralString(string s) {

            // If the string is long enough, and the compiler supports it, use a UTF8 resource 
            // string for performance
            return (s.Length >= minLongLiteralStringLength && _codeDomProvider.Supports(GeneratorSupport.Win32Resources)); 
        } 
    }
} 

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

namespace System.Web.Compilation { 
 
    using System;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.Reflection;
    using System.IO;
    using System.ComponentModel; 
    using System.CodeDom;
    using System.CodeDom.Compiler; 
    using System.Globalization; 
    using System.Web.UI;
    using System.Web.Util; 
    using System.Web.Configuration;
    using System.ComponentModel.Design;
    using Debug=System.Web.Util.Debug;
 
    internal abstract class BaseTemplateCodeDomTreeGenerator : BaseCodeDomTreeGenerator {
 
        protected static readonly string buildMethodPrefix = "__BuildControl"; 
        protected static readonly string extractTemplateValuesMethodPrefix = "__ExtractValues";
        protected static readonly string templateSourceDirectoryName = "AppRelativeTemplateSourceDirectory"; 
        protected static readonly string applyStyleSheetMethodName = "ApplyStyleSheetSkin";
        protected static readonly string pagePropertyName = "Page";
        internal const string skinIDPropertyName = "SkinID";
        private const string _localVariableRef = "__ctrl"; 

        private TemplateParser _parser; 
        private int _controlCount; 

        // Minimum literal string length for it to be placed in the resource 
        private const int minLongLiteralStringLength = 256;
        private const string renderMethodParameterName = "__w";

        // Used in designer mode 
        internal const string tempObjectVariable = "__o";
 
 
        /*
         * Set some fields that are needed for code generation 
         */
        internal BaseTemplateCodeDomTreeGenerator(TemplateParser parser) : base(parser) {
            _parser = parser;
        } 

        private TemplateParser Parser { 
            get { 
                return _parser;
            } 
        }

        private CodeStatement GetOutputWriteStatement(CodeExpression expr) {
 
            CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression();
            CodeExpressionStatement call = new CodeExpressionStatement(methodInvoke); 
            methodInvoke.Method.TargetObject = new CodeArgumentReferenceExpression(renderMethodParameterName); 
            methodInvoke.Method.MethodName = "Write";
 
            methodInvoke.Parameters.Add(expr);

            return call;
        } 

 
        ///  
        ///     Append an output.Write() statement to a Render method
        ///  
        private void AddOutputWriteStatement(CodeStatementCollection methodStatements,
                                     CodeExpression expr,
                                     CodeLinePragma linePragma) {
 
            CodeStatement outputWriteStmt = GetOutputWriteStatement(expr);
            if (linePragma != null) 
                outputWriteStmt.LinePragma = linePragma; 

            methodStatements.Add(outputWriteStmt); 
        }

        private void AddOutputWriteStringStatement(CodeStatementCollection methodStatements,
                                     String s) { 

            if (!UseResourceLiteralString(s)) { 
                AddOutputWriteStatement(methodStatements, new CodePrimitiveExpression(s), null); 
                return;
            } 

            // Add the string to the resource builder, and get back its offset/size
            int offset, size;
            bool fAsciiOnly; 
            _stringResourceBuilder.AddString(s, out offset, out size, out fAsciiOnly);
 
            // e.g. WriteUTF8ResourceString(output, 314, 20); 
            CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression();
            CodeExpressionStatement call = new CodeExpressionStatement(methodInvoke); 
            methodInvoke.Method.TargetObject = new CodeThisReferenceExpression();
            methodInvoke.Method.MethodName = "WriteUTF8ResourceString";
            methodInvoke.Parameters.Add(new CodeArgumentReferenceExpression(renderMethodParameterName));
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(offset)); 
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(size));
            methodInvoke.Parameters.Add(new CodePrimitiveExpression(fAsciiOnly)); 
            methodStatements.Add(call); 
        }
 
        private static void BuildAddParsedSubObjectStatement(
                    CodeStatementCollection statements, CodeExpression ctrlToAdd, CodeLinePragma linePragma, CodeExpression ctrlRefExpr, ref bool gotParserVariable) {

            if (!gotParserVariable) { 
                // e.g. IParserAccessor __parser = ((IParserAccessor)__ctrl);
                CodeVariableDeclarationStatement parserDeclaration = new CodeVariableDeclarationStatement(); 
                parserDeclaration.Name = "__parser"; 
                parserDeclaration.Type = new CodeTypeReference(typeof(IParserAccessor));
                parserDeclaration.InitExpression = new CodeCastExpression( 
                                                        typeof(IParserAccessor),
                                                        ctrlRefExpr);
                statements.Add(parserDeclaration);
                gotParserVariable = true; 
            }
 
            // e.g. __parser.AddParsedSubObject({{controlName}}); 
            CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression("__parser"), "AddParsedSubObject"); 
            methCallExpression.Parameters.Add(ctrlToAdd);
            CodeExpressionStatement methCallStatement = new CodeExpressionStatement(methCallExpression);
            methCallStatement.LinePragma = linePragma;
 
            statements.Add(methCallStatement);
        } 
 
        internal virtual CodeExpression BuildPagePropertyReferenceExpression() {
            return new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), pagePropertyName); 
        }

        /*
         * Build the data tree for a control's build method 
         */
        protected CodeMemberMethod BuildBuildMethod(ControlBuilder builder, bool fTemplate, 
            bool fInTemplate, bool topLevelControlInTemplate, PropertyEntry pse, bool fControlSkin) { 

            Debug.Assert(builder.ServiceProvider == null); 

            ServiceContainer container = new ServiceContainer();
            container.AddService(typeof(IFilterResolutionService), HttpCapabilitiesBase.EmptyHttpCapabilitiesBase);
 
            try {
                builder.SetServiceProvider(container); 
                builder.EnsureEntriesSorted(); 
            }
            finally { 
                builder.SetServiceProvider(null);
            }

            string methodName = GetMethodNameForBuilder(buildMethodPrefix, builder); 
            Type ctrlType = GetCtrlTypeForBuilder(builder, fTemplate);
            bool fStandardControl = false; 
            bool fControlFieldDeclared = false; 

            CodeMemberMethod method = new CodeMemberMethod(); 
            AddDebuggerNonUserCodeAttribute(method);
            method.Name = methodName;
            method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
 
            _sourceDataClass.Members.Add(method);
 
            // If it's for a template or a r/o complex prop, pass a parameter of the control's type 
            ComplexPropertyEntry cpse = pse as ComplexPropertyEntry;
            if (fTemplate || (cpse != null && cpse.ReadOnly)) { 
                if (builder is RootBuilder)
                    method.Parameters.Add(new CodeParameterDeclarationExpression(_sourceDataClass.Name, "__ctrl"));
                else
                    method.Parameters.Add(new CodeParameterDeclarationExpression(ctrlType, "__ctrl")); 
            }
            else { 
                // If it's a standard control, return it from the method 
                if (typeof(Control).IsAssignableFrom(builder.ControlType)) {
                    fStandardControl = true; 
                }

                Debug.Assert(builder.ControlType != null);
                if (builder.ControlType != null) { 
                    if (fControlSkin) {
                        // ReturnType needs to be of type Control in a skin file to match 
                        // the controlskin delegate. 
                        if (fStandardControl) {
                            method.ReturnType = new CodeTypeReference(typeof(Control)); 
                        }
                    }
                    else {
                        PartialCachingAttribute cacheAttrib = (PartialCachingAttribute) 
                            TypeDescriptor.GetAttributes(builder.ControlType)[typeof(PartialCachingAttribute)];
                        if (cacheAttrib != null) { 
                            method.ReturnType = new CodeTypeReference(typeof(Control)); 
                        }
                        else { 
                            // Otherwise the return type is always the actual component type.
                            method.ReturnType = new CodeTypeReference(builder.ControlType,
                                CodeTypeReferenceOptions.GlobalReference);
                        } 
                    }
                } 
 
                // A control field declaration is required, this field will be returned
                // in the method. 
                fControlFieldDeclared = true;
            }

            // Add a control parameter if it's a ControlSkin 
            if (fControlSkin) {
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control).FullName, "ctrl")); 
            } 

            BuildBuildMethodInternal(builder, builder.ControlType, fInTemplate, topLevelControlInTemplate, pse, 
                method.Statements, fStandardControl, fControlFieldDeclared, null, fControlSkin);

            return method;
        } 

        /* Helper method to generate the content of the control's build method 
         *  Type _ctrl; 
         *  _ctrl = new Type();
         *      ... 
         *  return _ctrl;
         */
        private void BuildBuildMethodInternal(ControlBuilder builder, Type ctrlType, bool fInTemplate,
            bool topLevelControlInTemplate, PropertyEntry pse, CodeStatementCollection statements, 
            bool fStandardControl, bool fControlFieldDeclared, string deviceFilter, bool fControlSkin) {
 
            // Same linePragma in the entire build method 
            CodeLinePragma linePragma = CreateCodeLinePragma(builder);
 
            CodeObjectCreateExpression newExpr;
            CodeExpressionStatement methCallStatement;
            CodeMethodInvokeExpression methCallExpression;
 
            CodeExpression ctrlRefExpr;
 
            if (fControlSkin) { 
                CodeCastExpression cast = new CodeCastExpression(builder.ControlType.FullName,
                                           new CodeArgumentReferenceExpression("ctrl")); 
                statements.Add(new CodeVariableDeclarationStatement(builder.ControlType.FullName, "__ctrl", cast));
                ctrlRefExpr = new CodeVariableReferenceExpression("__ctrl");
            }
            // Not a control. ie. it's for a template or a r/o complex prop, 
            else if (!fControlFieldDeclared) {
                ctrlRefExpr = new CodeArgumentReferenceExpression("__ctrl"); 
            } 
            else {
                CodeTypeReference ctrlTypeRef = new CodeTypeReference(ctrlType, 
                    CodeTypeReferenceOptions.GlobalReference);

                newExpr = new CodeObjectCreateExpression(ctrlTypeRef);
 
                // If it has a ConstructorNeedsTagAttribute, it needs a tag name
                ConstructorNeedsTagAttribute cnta = (ConstructorNeedsTagAttribute) 
                    TypeDescriptor.GetAttributes(ctrlType)[typeof(ConstructorNeedsTagAttribute)]; 

                if (cnta != null && cnta.NeedsTag) { 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(builder.TagName));
                }

                // If it's for a DataBoundLiteralControl, pass it the number of 
                // entries in the constructor
                DataBoundLiteralControlBuilder dataBoundBuilder = builder as DataBoundLiteralControlBuilder; 
                if (dataBoundBuilder != null) { 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(
                        dataBoundBuilder.GetStaticLiteralsCount())); 
                    newExpr.Parameters.Add(new CodePrimitiveExpression(
                        dataBoundBuilder.GetDataBoundLiteralCount()));
                }
 
                // e.g. {{controlTypeName}} __ctrl;
                statements.Add(new CodeVariableDeclarationStatement(ctrlTypeRef, "__ctrl")); 
                ctrlRefExpr = new CodeVariableReferenceExpression("__ctrl"); 

                // e.g. __ctrl = new {{controlTypeName}}(); 
                CodeAssignStatement setCtl = new CodeAssignStatement(ctrlRefExpr, newExpr);
                setCtl.LinePragma = linePragma;
                statements.Add(setCtl);
 
                if (!builder.IsGeneratedID) {
                    // Assign the local control reference to the global control variable 
                    CodeFieldReferenceExpression ctrlNameExpr = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), builder.ID); 

                    // e.g. {{controlName}} = __ctrl; 
                    CodeAssignStatement underscoreCtlSet = new CodeAssignStatement(ctrlNameExpr, ctrlRefExpr);
                    statements.Add(underscoreCtlSet);
                }
 
                // Don't do this if the control is itself a TemplateControl, in which case it
                // will point its TemplateControl property to itself (instead of its parent 
                // TemplateControl).  VSWhidbey 214356. 
                if (topLevelControlInTemplate && !typeof(TemplateControl).IsAssignableFrom(ctrlType)) {
                    statements.Add(BuildTemplatePropertyStatement(ctrlRefExpr)); 
                }

                if (fStandardControl) {
                    // e.g. __ctrl.SkinID = {{skinID}}; 
                    if (builder.SkinID != null) {
                        CodeAssignStatement set = new CodeAssignStatement(); 
                        set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, skinIDPropertyName); 
                        set.Right = new CodePrimitiveExpression(builder.SkinID);
                        statements.Add(set); 
                    }

                    // e.g. __ctrl.ApplyStyleSheetSkin(this);
                    if (ThemeableAttribute.IsTypeThemeable(ctrlType)) { 
                        // e.g. __ctrl.ApplyStyleSheetSkin(this.Page);
                        CodeMethodInvokeExpression applyStyleSheetExpr = new CodeMethodInvokeExpression(ctrlRefExpr, applyStyleSheetMethodName); 
                        applyStyleSheetExpr.Parameters.Add(BuildPagePropertyReferenceExpression()); 

                        statements.Add(applyStyleSheetExpr); 
                    }
                }
            }
 
            // Process the templates
            if (builder.TemplatePropertyEntries.Count > 0) { 
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts; 
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null;

                foreach (TemplatePropertyEntry pseSub in builder.TemplatePropertyEntries) { 
                    currentStmts = nextStmts;
 
                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts); 

                    string controlName = pseSub.Builder.ID; 
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                    newDelegate.DelegateType = new CodeTypeReference(typeof(BuildTemplateMethod));
                    newDelegate.TargetObject = new CodeThisReferenceExpression();
                    newDelegate.MethodName = buildMethodPrefix + controlName; 

                    CodeAssignStatement set = new CodeAssignStatement(); 
                    if (pseSub.PropertyInfo != null) { 
                        set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);
                    } 
                    else {
                        set.Left = new CodeFieldReferenceExpression(ctrlRefExpr, pseSub.Name);
                    }
 
                    if (pseSub.BindableTemplate) {
                        // e.g. __ctrl.{{templateName}} = new CompiledBindableTemplateBuilder( 
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}}), 
                        // e.g.     new ExtractTemplateValuesMethod(this.__ExtractValues {{controlName}}));
                        CodeExpression newExtractValuesDelegate; 
                        if (pseSub.Builder.HasTwoWayBoundProperties) {
                            newExtractValuesDelegate = new CodeDelegateCreateExpression();
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).DelegateType = new CodeTypeReference(typeof(ExtractTemplateValuesMethod));
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).TargetObject = new CodeThisReferenceExpression(); 
                            ((CodeDelegateCreateExpression)newExtractValuesDelegate).MethodName = extractTemplateValuesMethodPrefix + controlName;
                        } 
                        else { 
                            newExtractValuesDelegate = new CodePrimitiveExpression(null);
                        } 

                        newExpr = new CodeObjectCreateExpression(typeof(CompiledBindableTemplateBuilder));
                        newExpr.Parameters.Add(newDelegate);
                        newExpr.Parameters.Add(newExtractValuesDelegate); 

                    } 
                    else { 
                        // e.g. __ctrl.{{templateName}} = new CompiledTemplateBuilder(
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}})); 
                        newExpr = new CodeObjectCreateExpression(typeof(CompiledTemplateBuilder));
                        newExpr.Parameters.Add(newDelegate);

                    } 
                    set.Right = newExpr;
                    set.LinePragma = CreateCodeLinePragma(pseSub.Builder); 
                    currentStmts.Add(set); 
                }
            } 

            // Is this BuilderData for a declarative control?  If so initialize it (75330)
            // Only do this is the control field has been declared (i.e. not with templates)
            if (typeof(UserControl).IsAssignableFrom(ctrlType) && fControlFieldDeclared && !fControlSkin) { 
                // e.g. _ctrl.InitializeAsUserControl(Context, Page);
                methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "InitializeAsUserControl"); 
                methCallExpression.Parameters.Add(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), pagePropertyName)); 
                methCallStatement = new CodeExpressionStatement(methCallExpression);
                methCallStatement.LinePragma = linePragma; 
                statements.Add(methCallStatement);
            }

            // Process the simple attributes 
            if (builder.SimplePropertyEntries.Count > 0) {
                // Used to deal with the device filter conditionals 
                CodeStatementCollection currentStmts; 
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null; 

                foreach (SimplePropertyEntry pseSub in builder.SimplePropertyEntries) {
                    currentStmts = nextStmts;
 
                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts);
 
                    CodeStatement statement = pseSub.GetCodeStatement(this, ctrlRefExpr); 
                    statement.LinePragma = linePragma;
                    currentStmts.Add(statement); 
                }
            }

            // Call the helper method for allowing page developers to customize culture settings 
            if (typeof(Page).IsAssignableFrom(ctrlType) && !fControlSkin) {
                // e.g. this.InitializeCulture(); 
                methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InitializeCulture"); 
                methCallStatement = new CodeExpressionStatement(methCallExpression);
                methCallStatement.LinePragma = linePragma; 
                statements.Add(methCallStatement);
            }

            // Automatic template support (i.e. ) 
            CodeMethodInvokeExpression instantiateTemplateExpr = null;
            CodeConditionStatement templateIfStmt = null; 
            CodeStatementCollection buildSubControlBlock = statements; 
            string autoTemplateName = null;
            if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) { 

                string templateName = ((System.Web.UI.WebControls.ContentPlaceHolderBuilder)builder).Name;
                autoTemplateName = MasterPageControlBuilder.AutoTemplatePrefix + templateName;
 
                Debug.Assert(autoTemplateName != null && autoTemplateName.Length > 0, "Template Name is empty.");
 
                // Generate a private field and public property for the ITemplate 
                string fieldName = "__"+ autoTemplateName;
 
                Type containerType = builder.BindingContainerType;
                // Use the base class or template type if INamingContainer cannot be found.
                if (!typeof(INamingContainer).IsAssignableFrom(containerType)) {
                    if (typeof(INamingContainer).IsAssignableFrom(Parser.BaseType)) { 
                        containerType = Parser.BaseType;
                    } 
                    else { 
                        // This should not occur as all base classes are namingcontainers.
                        Debug.Assert(false, "baseClassType is not an INamingContainer"); 
                        containerType = typeof(System.Web.UI.Control);
                    }
                }
 
                CodeAttributeDeclarationCollection attrDeclarations = new CodeAttributeDeclarationCollection();
 
                CodeAttributeDeclaration templateContainerAttrDeclaration = new CodeAttributeDeclaration( 
                    "TemplateContainer",
                    new CodeAttributeArgument[] { 
                        new CodeAttributeArgument(new CodeTypeOfExpression(containerType))});

                attrDeclarations.Add(templateContainerAttrDeclaration);
 
                // If the template control is in a template, assume its container allows multiple instances,
                // otherwise set the TemplateInstanceAttribute 
                if (fInTemplate == false) { 
                    CodeAttributeDeclaration templateInstanceAttrDeclaration = new CodeAttributeDeclaration(
                        "TemplateInstanceAttribute", 
                        new CodeAttributeArgument[] {
                            new CodeAttributeArgument(
                                new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(TemplateInstance)),
                                                                 "Single"))}); 
                    attrDeclarations.Add(templateInstanceAttrDeclaration);
                } 
 
                BuildFieldAndAccessorProperty(autoTemplateName, fieldName, typeof(ITemplate), false /*fStatic*/, attrDeclarations);
                CodeExpression templateFieldRef = new CodeFieldReferenceExpression( 
                    new CodeThisReferenceExpression(), fieldName);

                if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) {
                    // We generate something like this: 
                    // if (this.ContentTemplates != null) {
                    //     this.__Template_TestTemplate = (ITemplate)this.ContentTemplates[{templateName}]; 
                    // } 
                    CodePropertyReferenceExpression contentTemplatesFieldRef =
                        new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ContentTemplates"); 

                    CodeAssignStatement setStatement = new CodeAssignStatement();
                    setStatement.Left = templateFieldRef;
                    setStatement.Right = new CodeCastExpression(typeof(ITemplate), new CodeIndexerExpression(contentTemplatesFieldRef, 
                                                                                       new CodePrimitiveExpression(templateName)));
 
                    CodeConditionStatement contentTemplateIfStmt = new CodeConditionStatement(); 

                    CodeBinaryOperatorExpression contentNullCheckExpr = new CodeBinaryOperatorExpression(contentTemplatesFieldRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)); 

                    CodeMethodInvokeExpression removeExpr = new CodeMethodInvokeExpression(contentTemplatesFieldRef, "Remove");
                    removeExpr.Parameters.Add(new CodePrimitiveExpression(templateName));
 
                    contentTemplateIfStmt.Condition = contentNullCheckExpr;
                    contentTemplateIfStmt.TrueStatements.Add(setStatement); 
 
                    statements.Add(contentTemplateIfStmt);
                } 

                // We generate something like this:
                // if ((this.__Template_TestTemplate != null)) {
                //     this.__Template_TestTemplate.InstantiateIn(__ctrl); 
                // }
                // else { 
                //     // normal sub control building code 
                // }
                instantiateTemplateExpr = new CodeMethodInvokeExpression(templateFieldRef, "InstantiateIn"); 
                instantiateTemplateExpr.Parameters.Add(ctrlRefExpr);

                templateIfStmt = new CodeConditionStatement();
                templateIfStmt.Condition = new CodeBinaryOperatorExpression(templateFieldRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)); 
                templateIfStmt.TrueStatements.Add(new CodeExpressionStatement(instantiateTemplateExpr));
                buildSubControlBlock = templateIfStmt.FalseStatements; 
                statements.Add(templateIfStmt); 
            }
 
            ICollection contentBuilderEntries = null;
            if (builder is FileLevelPageControlBuilder) {
                contentBuilderEntries = ((FileLevelPageControlBuilder)builder).ContentBuilderEntries;
 
                if (contentBuilderEntries != null) {
                    CodeStatementCollection currentStmts; 
                    CodeStatementCollection nextStmts = statements; 
                    PropertyEntry previous = null;
 
                    foreach (TemplatePropertyEntry entry in contentBuilderEntries) {
                        System.Web.UI.WebControls.ContentBuilderInternal child =
                            (System.Web.UI.WebControls.ContentBuilderInternal)entry.Builder;
 
                        currentStmts = nextStmts;
 
                        HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStmts, out nextStmts); 

                        string controlName = child.ID; 
                        string contentPlaceHolderID = child.ContentPlaceHolder;

                        CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                        newDelegate.DelegateType = new CodeTypeReference(typeof(BuildTemplateMethod)); 
                        newDelegate.TargetObject = new CodeThisReferenceExpression();
                        newDelegate.MethodName = buildMethodPrefix + controlName; 
 
                        // e.g. this.AddContentTemplate(contentPlaceHolderID, new CompiledTemplateBuilder(
                        // e.g.     new BuildTemplateMethod(this.__BuildControl {{controlName}})); 
                        CodeObjectCreateExpression cocExpr = new CodeObjectCreateExpression(typeof(CompiledTemplateBuilder));
                        cocExpr.Parameters.Add(newDelegate);

                        CodeMethodInvokeExpression cmiExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "AddContentTemplate"); 
                        cmiExpression.Parameters.Add(new CodePrimitiveExpression(contentPlaceHolderID));
                        cmiExpression.Parameters.Add(cocExpr); 
 
                        CodeExpressionStatement ceStatement = new CodeExpressionStatement(cmiExpression);
                        ceStatement.LinePragma = CreateCodeLinePragma((ControlBuilder)child); 

                        currentStmts.Add(ceStatement);
                    }
                } 
            }
 
            if (builder is DataBoundLiteralControlBuilder) { 

                // If it's a DataBoundLiteralControl, build it by calling SetStaticString 
                // on all the static literal strings.
                int i = -1;
                foreach (object child in builder.SubBuilders) {
                    i++; 

                    // Ignore it if it's null 
                    if (child == null) 
                        continue;
 
                    // Only deal with the strings here, which have even index
                    if (i % 2 == 1) {
                        Debug.Assert(child is CodeBlockBuilder, "child is CodeBlockBuilder");
                        continue; 
                    }
 
                    string s = (string) child; 

                    // e.g. __ctrl.SetStaticString(3, "literal string"); 
                    methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "SetStaticString");
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(i/2));
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(s));
                    statements.Add(new CodeExpressionStatement(methCallExpression)); 
                }
            } 
            // Process the children 
            else if (builder.SubBuilders != null) {
 
                bool gotParserVariable = false;
                int localVarIndex = 1;

                foreach (object child in builder.SubBuilders) { 
                    if (child is ControlBuilder && !(child is CodeBlockBuilder) && !(child is System.Web.UI.WebControls.ContentBuilderInternal)) {
                        ControlBuilder ctrlBuilder = (ControlBuilder) child; 
 
                        if (fControlSkin) {
                            throw new HttpParseException(SR.GetString(SR.ControlSkin_cannot_contain_controls), 
                                null,
                                builder.VirtualPath, null, builder.Line);
                        }
 
                        PartialCachingAttribute cacheAttrib = (PartialCachingAttribute)
                            TypeDescriptor.GetAttributes(ctrlBuilder.ControlType)[typeof(PartialCachingAttribute)]; 
 
                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + ctrlBuilder.ID); 
                        methCallStatement = new CodeExpressionStatement(methCallExpression);

                        if (cacheAttrib == null) {
                            string localVariableRef = _localVariableRef + (localVarIndex++).ToString(CultureInfo.InvariantCulture); 

                            // Variable reference to the local control variable 
                            CodeVariableReferenceExpression childCtrlRefExpr = new CodeVariableReferenceExpression(localVariableRef); 

                            // e.g. {{controlTypeName}} ctrl5; 
                            CodeTypeReference ctrlTypeReference =
                                new CodeTypeReference(ctrlBuilder.ControlType, CodeTypeReferenceOptions.GlobalReference);
                            buildSubControlBlock.Add(new CodeVariableDeclarationStatement(ctrlTypeReference, localVariableRef));
 
                            // e.g. ctrl5 = __BuildControl__control6();
                            CodeAssignStatement setCtl = new CodeAssignStatement(childCtrlRefExpr, methCallExpression); 
                            setCtl.LinePragma = linePragma; 
                            buildSubControlBlock.Add(setCtl);
 
                            // If there is no caching on the control, just create it and add it
                            // e.g. __parser.AddParsedSubObject(ctrl5);
                            BuildAddParsedSubObjectStatement(
                                buildSubControlBlock, 
                                childCtrlRefExpr,
                                linePragma, 
                                ctrlRefExpr, 
                                ref gotParserVariable);
                        } 
                        else {
                            // The control's output is getting cached.  Call
                            // StaticPartialCachingControl.BuildCachedControl to do the work.
 
                            // e.g. StaticPartialCachingControl.BuildCachedControl(__ctrl, Request, "e4192e6d-cbe0-4df5-b516-682c10415590", __pca, new System.Web.UI.BuildMethod(this.__BuildControlt1));
                            CodeMethodInvokeExpression call = new CodeMethodInvokeExpression(); 
                            call.Method.TargetObject = new CodeTypeReferenceExpression(typeof(System.Web.UI.StaticPartialCachingControl)); 
                            call.Method.MethodName = "BuildCachedControl";
                            call.Parameters.Add(ctrlRefExpr); 
                            call.Parameters.Add(new CodePrimitiveExpression(ctrlBuilder.ID));

                            // If the caching is shared, use the type of the control as the key
                            // otherwise, generate a guid 
                            if (cacheAttrib.Shared) {
                                call.Parameters.Add(new CodePrimitiveExpression( 
                                    ctrlBuilder.ControlType.GetHashCode().ToString(CultureInfo.InvariantCulture))); 
                            }
                            else 
                                call.Parameters.Add(new CodePrimitiveExpression(Guid.NewGuid().ToString()));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.Duration));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByParams));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByControls)); 
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.VaryByCustom));
                            call.Parameters.Add(new CodePrimitiveExpression(cacheAttrib.SqlDependency)); 
                            CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression(); 
                            newDelegate.DelegateType = new CodeTypeReference(typeof(BuildMethod));
                            newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                            newDelegate.MethodName = buildMethodPrefix + ctrlBuilder.ID;
                            call.Parameters.Add(newDelegate);
                            buildSubControlBlock.Add(new CodeExpressionStatement(call));
                        } 

                    } 
                    else if (child is string && !builder.HasAspCode) { 

                        // VSWhidbey 276806: if the control cares about the inner text (builder does not allow whitespace literals) 
                        // the inner literals should be added to the control.
                        if (!fControlSkin || !builder.AllowWhitespaceLiterals()) {
                            string s = (string) child;
                            CodeExpression expr; 

                            if (!UseResourceLiteralString(s)) { 
                                // e.g. ((IParserAccessor)__ctrl).AddParsedSubObject(new LiteralControl({{@QuoteCString(text)}})); 
                                newExpr = new CodeObjectCreateExpression(typeof(LiteralControl));
                                newExpr.Parameters.Add(new CodePrimitiveExpression(s)); 
                                expr = newExpr;
                            }
                            else {
                                // Add the string to the resource builder, and get back its offset/size 
                                int offset, size;
                                bool fAsciiOnly; 
                                _stringResourceBuilder.AddString(s, out offset, out size, out fAsciiOnly); 

                                methCallExpression = new CodeMethodInvokeExpression(); 
                                methCallExpression.Method.TargetObject = new CodeThisReferenceExpression();
                                methCallExpression.Method.MethodName = "CreateResourceBasedLiteralControl";
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(offset));
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(size)); 
                                methCallExpression.Parameters.Add(new CodePrimitiveExpression(fAsciiOnly));
                                expr = methCallExpression; 
                            } 

                            BuildAddParsedSubObjectStatement(buildSubControlBlock, expr, linePragma, ctrlRefExpr, ref gotParserVariable); 
                        }
                    }
                }
            } 

            // Process the complex attributes 
            if (builder.ComplexPropertyEntries.Count > 0) { 

                // Used to deal with the device filter conditionals 
                CodeStatementCollection currentStmts;
                CodeStatementCollection nextStmts = statements;
                PropertyEntry previous = null;
                int localVarIndex = 1; 
                String localVariableRef = null;
 
                foreach (ComplexPropertyEntry pseSub in builder.ComplexPropertyEntries) { 

                    currentStmts = nextStmts; 

                    HandleDeviceFilterConditional(ref previous, pseSub, statements, ref currentStmts, out nextStmts);

                    if (pseSub.Builder is StringPropertyBuilder) { 
                        // If it's a string inner property, treat it like a simple property
                        CodeExpression leftExpr, rightExpr = null; 
 
                        // __ctrl.{{_name}}
                        // In case of a string property, there should only be one property name (unlike complex properties) 
                        Debug.Assert(pseSub.Name.IndexOf('.') < 0, "pseSub._name.IndexOf('.') < 0");
                        leftExpr = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);

                        // We need to call BuildStringPropertyExpression so any additional processing can be done 
                        rightExpr = BuildStringPropertyExpression(pseSub);
 
                        // Now that we have both side, add the assignment 
                        CodeAssignStatement setStatment = new CodeAssignStatement(leftExpr, rightExpr);
                        setStatment.LinePragma = linePragma; 
                        currentStmts.Add(setStatment);

                        continue;
                    } 

                    if (pseSub.ReadOnly) { 
 
                        if (fControlSkin && pseSub.Builder != null && pseSub.Builder is CollectionBuilder &&
                        pseSub.Builder.ComplexPropertyEntries.Count > 0) { 

                            // If it's a collection on a control theme and the themed collection is not empty, clear it first.
                            // e.g. __ctrl.{{pse_name}}.Clear();
 
                            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
                            // Look for the "Clear" method on the collection. 
                            if (pseSub.Type.GetMethod("Clear", bindingFlags) != null) { 
                                CodeMethodReferenceExpression refExpr = new CodeMethodReferenceExpression();
                                refExpr.MethodName = "Clear"; 
                                refExpr.TargetObject = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name);
                                CodeMethodInvokeExpression invokeClearExpr = new CodeMethodInvokeExpression();
                                invokeClearExpr.Method = refExpr;
                                currentStmts.Add(invokeClearExpr); 
                            }
                        } 
 
                        // If it's a readonly prop, pass it as a parameter to the
                        // build method. 
                        // e.g. __BuildControl {{controlName}}(__ctrl.{{pse._name}});
                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + pseSub.Builder.ID);
                        methCallExpression.Parameters.Add(new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name)); 
                        methCallStatement = new CodeExpressionStatement(methCallExpression);
                        methCallStatement.LinePragma = linePragma; 
                        currentStmts.Add(methCallStatement); 
                    }
                    else { 
                        localVariableRef = _localVariableRef + (localVarIndex++).ToString(CultureInfo.InvariantCulture);

                        // e.g. {{controlTypeName}} ctrl4;
                        CodeTypeReference ctrlTypeReference = 
                            new CodeTypeReference(pseSub.Builder.ControlType, CodeTypeReferenceOptions.GlobalReference);
                        currentStmts.Add(new CodeVariableDeclarationStatement(ctrlTypeReference, localVariableRef)); 
 
                        // Variable reference to the local control variable.
                        CodeVariableReferenceExpression childCtrlRefExpr = new CodeVariableReferenceExpression(localVariableRef); 

                        methCallExpression = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                                                                          buildMethodPrefix + pseSub.Builder.ID);
                        methCallStatement = new CodeExpressionStatement(methCallExpression); 

                        // e.g. ctrl4 = __BuildControl {{controlName}}(); 
                        CodeAssignStatement setCtl = new CodeAssignStatement(childCtrlRefExpr, methCallExpression); 
                        setCtl.LinePragma = linePragma;
                        currentStmts.Add(setCtl); 

                        if (pseSub.IsCollectionItem) {
                            // e.g. __ctrl.Add(ctrl4);
                            methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "Add"); 
                            methCallStatement = new CodeExpressionStatement(methCallExpression);
                            methCallStatement.LinePragma = linePragma; 
                            currentStmts.Add(methCallStatement); 
                            methCallExpression.Parameters.Add(childCtrlRefExpr);
                        } 
                        else {
                            // e.g. __ctrl.{{pse._name}} = {{controlName}};
                            CodeAssignStatement set = new CodeAssignStatement();
                            set.Left = new CodePropertyReferenceExpression(ctrlRefExpr, pseSub.Name); 
                            set.Right = childCtrlRefExpr;
                            set.LinePragma = linePragma; 
                            currentStmts.Add(set); 
                        }
                    } 
                }
            }

            // If there are bound properties, hook up the binding method 
            if (builder.BoundPropertyEntries.Count > 0) {
 
                bool isBindableTemplateBuilder = builder is BindableTemplateBuilder; 
                bool hasDataBindingEntry = false;
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts;
                CodeStatementCollection methodStatements = statements;
                CodeStatementCollection nextStmts = statements; 
                PropertyEntry previous = null;
 
                bool hasTempObject = false; 

                foreach (BoundPropertyEntry entry in builder.BoundPropertyEntries) { 

                    // Skip two-way entries if it's a BindableTemplateBuilder or the two-way entry has no setter
                    if (entry.TwoWayBound && (isBindableTemplateBuilder || entry.ReadOnlyProperty))
                        continue; 

                    if (entry.IsDataBindingEntry) { 
                        hasDataBindingEntry = true; 
                        continue;
                    } 

                    currentStmts = nextStmts;

                    HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStmts, out nextStmts); 

                    ExpressionBuilder eb = entry.ExpressionBuilder; 
                    Debug.Assert(eb != null, "Did not expect null expression builder"); 
                    eb.BuildExpression(entry, builder, ctrlRefExpr, methodStatements, currentStmts, null, ref hasTempObject);
                } 

                if (hasDataBindingEntry) {

                    EventInfo eventInfo = DataBindingExpressionBuilder.Event; 

                    // __ctrl.{EventName} += new EventHandler(this.{{bindingMethod}}) 
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression(); 
                    CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, eventInfo.Name, newDelegate);
                    attachEvent.LinePragma = linePragma; 
                    newDelegate.DelegateType = new CodeTypeReference(typeof(EventHandler));
                    newDelegate.TargetObject = new CodeThisReferenceExpression();
                    newDelegate.MethodName = GetExpressionBuilderMethodName(eventInfo.Name, builder);
                    statements.Add(attachEvent); 
                }
            } 
 
            if (builder is DataBoundLiteralControlBuilder) {
 
                // __ctrl.DataBinding += new EventHandler(this.{{bindingMethod}})
                CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, "DataBinding", newDelegate);
                attachEvent.LinePragma = linePragma; 
                newDelegate.DelegateType = new CodeTypeReference(typeof(EventHandler));
                newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                newDelegate.MethodName = BindingMethodName(builder); 
                statements.Add(attachEvent);
            } 

            // If there is any ASP code, set the render method delegate
            if (builder.HasAspCode && !fControlSkin) {
                // e.g. __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render {{controlName}})); 
                CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                newDelegate.DelegateType = new CodeTypeReference(typeof(RenderMethod)); 
                newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                newDelegate.MethodName = "__Render" + builder.ID;
 
                methCallExpression = new CodeMethodInvokeExpression(ctrlRefExpr, "SetRenderMethodDelegate");
                methCallExpression.Parameters.Add(newDelegate);
                methCallStatement = new CodeExpressionStatement(methCallExpression);
 
                // VSWhidbey 579101
                // If this is a contentPlaceHolder, we need to check if there is any content defined. 
                // We set the render method only when there is no contentTemplate defined. 
                // if ((this.__Template_TestTemplate == null)) {
                //     __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render {{controlName}})); 
                // }
                if (builder is System.Web.UI.WebControls.ContentPlaceHolderBuilder) {
                    string templateName = ((System.Web.UI.WebControls.ContentPlaceHolderBuilder)builder).Name;
                    autoTemplateName = MasterPageControlBuilder.AutoTemplatePrefix + templateName; 
                    string fieldName = "__" + autoTemplateName;
                    CodeExpression templateFieldRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName); 
                    templateIfStmt = new CodeConditionStatement(); 
                    templateIfStmt.Condition = new CodeBinaryOperatorExpression(templateFieldRef, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null));
                    templateIfStmt.TrueStatements.Add(methCallStatement); 
                    statements.Add(templateIfStmt);
                }
                else {
                    statements.Add(methCallStatement); 
                }
            } 
 
            // Process the events
            if (builder.EventEntries.Count > 0) { 

                foreach (EventEntry eventEntry in builder.EventEntries) {

                    // Attach the event.  Detach it first to avoid duplicates (see ASURT 42603), 
                    // but only if there is codebehind
                    // 
 

                    // e.g. __ctrl.ServerClick -= new System.EventHandler(this.buttonClicked); 
                    // e.g. __ctrl.ServerClick += new System.EventHandler(this.buttonClicked);
                    CodeDelegateCreateExpression newDelegate = new CodeDelegateCreateExpression();
                    newDelegate.DelegateType = new CodeTypeReference(eventEntry.HandlerType);
                    newDelegate.TargetObject = new CodeThisReferenceExpression(); 
                    newDelegate.MethodName = eventEntry.HandlerMethodName;
 
                    if (Parser.HasCodeBehind) { 
                        CodeRemoveEventStatement detachEvent = new CodeRemoveEventStatement(ctrlRefExpr, eventEntry.Name, newDelegate);
                        detachEvent.LinePragma = linePragma; 
                        statements.Add(detachEvent);
                    }

                    CodeAttachEventStatement attachEvent = new CodeAttachEventStatement(ctrlRefExpr, eventEntry.Name, newDelegate); 
                    attachEvent.LinePragma = linePragma;
                    statements.Add(attachEvent); 
                } 
            }
 
            // If a control field is declared, we need to return it at the end of the method.
            if (fControlFieldDeclared)
                statements.Add(new CodeMethodReturnStatement(ctrlRefExpr));
        } 

        /* 
         * Build the template's method to extract values from contained controls 
         */
        protected void BuildExtractMethod(ControlBuilder builder) { 
            BindableTemplateBuilder bindableTemplateBuilder = builder as BindableTemplateBuilder;
            // This will get called if Bind is in a non-bindable template.  We should just skip the Extract method.
            if (bindableTemplateBuilder != null && bindableTemplateBuilder.HasTwoWayBoundProperties) {
                // Get the name of the databinding method 
                string methodName = ExtractMethodName(builder);
                const string tableVarName = "__table"; 
                const string containerVarName = "__container"; 

                // Same linePragma in the entire method 
                CodeLinePragma linePragma = CreateCodeLinePragma(builder);

                CodeMemberMethod method = new CodeMemberMethod();
                AddDebuggerNonUserCodeAttribute(method); 
                method.Name = methodName;
                method.Attributes &= ~MemberAttributes.AccessMask; 
                method.Attributes |= MemberAttributes.Public; 
                method.ReturnType = new CodeTypeReference(typeof(IOrderedDictionary));
                _sourceDataClass.Members.Add(method); 

                /// Variable declarations need to go at the top for CodeDom compliance.
                CodeStatementCollection topLevelStatements = method.Statements;
                CodeStatementCollection statements = new CodeStatementCollection(); 

                // add a container control parameter 
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control), containerVarName)); 

                // OrderedDictionary table; 
                CodeVariableDeclarationStatement tableDecl = new CodeVariableDeclarationStatement(typeof(OrderedDictionary), tableVarName);
                topLevelStatements.Add(tableDecl);

                // table = new OrderedDictionary(); 
                CodeObjectCreateExpression newTableExpression = new CodeObjectCreateExpression(typeof(OrderedDictionary));
                CodeAssignStatement newTableAssign = new CodeAssignStatement(new CodeVariableReferenceExpression(tableVarName), 
                                                                             newTableExpression); 
                newTableAssign.LinePragma = linePragma;
                statements.Add(newTableAssign); 

                BuildExtractStatementsRecursive(bindableTemplateBuilder.SubBuilders, statements, topLevelStatements, linePragma, tableVarName, containerVarName);

                // return table; 
                CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(new CodeVariableReferenceExpression(tableVarName));
                statements.Add(returnStatement); 
 
                // add all the non-variable declaration statements to the bottom of the method
                method.Statements.AddRange(statements); 
            }
        }

        private void BuildExtractStatementsRecursive(ArrayList subBuilders, CodeStatementCollection statements, CodeStatementCollection topLevelStatements, CodeLinePragma linePragma, string tableVarName, string containerVarName) { 
            foreach (object subBuilderObject in subBuilders) {
                ControlBuilder controlBuilder = subBuilderObject as ControlBuilder; 
                if (controlBuilder != null) { 
                    // Used to deal with the device filter conditionals
                    CodeStatementCollection currentStatements = null; 
                    CodeStatementCollection nextStatements = statements;
                    PropertyEntry previous = null;
                    string previousControlName = null;
                    bool newControl = true; 

                    foreach (BoundPropertyEntry entry in controlBuilder.BoundPropertyEntries) { 
 
                        // Skip all entries that are not two-way
                        if (!entry.TwoWayBound) 
                            continue;

                        // Reset the "previous" Property Entry if we're not looking at the same control.
                        // If we don't do this, Two controls that have conditionals on the same named property will have 
                        // their conditionals incorrectly merged.
                        if (String.Compare(previousControlName, entry.ControlID, StringComparison.Ordinal) != 0) { 
                            previous = null; 
                            newControl = true;
                        } 
                        else {
                            newControl = false;
                        }
 
                        previousControlName = entry.ControlID;
                        currentStatements = nextStatements; 
 
                        HandleDeviceFilterConditional(ref previous, entry, statements, ref currentStatements, out nextStatements);
 
                        // Only declare the variable if it hasn't already been declared by a previous filter
                        // or property binding on the same control.
                        if (newControl) {
                            // {{controlType}} {{controlID}}; 
                            // eg. TextBox t1;
                            CodeVariableDeclarationStatement controlDecl = new CodeVariableDeclarationStatement(entry.ControlType, entry.ControlID); 
                            topLevelStatements.Add(controlDecl); 

                            // {{controlID}} = ({{controlType}})container.FindControl("{{controlID}}"); 
                            // eg. t1 = (TextBox)container.FindControl("t1");
                            CodeMethodInvokeExpression findControlCallExpression = new CodeMethodInvokeExpression(
                                    new CodeVariableReferenceExpression(containerVarName), "FindControl");
                            string findControlParameter = entry.ControlID; 
                            findControlCallExpression.Parameters.Add(new CodePrimitiveExpression(findControlParameter));
                            CodeCastExpression castExpression = new CodeCastExpression(entry.ControlType, findControlCallExpression); 
 
                            CodeAssignStatement findControlAssign = new CodeAssignStatement(new CodeVariableReferenceExpression(entry.ControlID),
                                                                                            castExpression); 
                            findControlAssign.LinePragma = linePragma;
                            topLevelStatements.Add(findControlAssign);
                        }
 
                        // if ({{controlID}} != null)
                        //     table["{{fieldName}}"] = {{controlID}}.{{propertyName}}); 
                        // eg. if (t1 != null) 
                        // eg.     table["field"] = t1.Text);
                        CodeConditionStatement ifStatement = new CodeConditionStatement(); 
                        CodeBinaryOperatorExpression ensureControlExpression = new CodeBinaryOperatorExpression();
                        ensureControlExpression.Operator = CodeBinaryOperatorType.IdentityInequality;
                        ensureControlExpression.Left = new CodeVariableReferenceExpression(entry.ControlID);
                        ensureControlExpression.Right = new CodePrimitiveExpression(null); 
                        ifStatement.Condition = ensureControlExpression;
 
                        string fieldParameter = entry.FieldName; 
                        CodeIndexerExpression tableIndexer = new CodeIndexerExpression(new CodeVariableReferenceExpression(tableVarName),
                                                                                       new CodePrimitiveExpression(fieldParameter)); 

                        // VJ# does not support automatic boxing of value types, so passing a simple type, say a bool, into a method
                        // expecting an object will give a compiler error.  We are working around this issue by adding special code for
                        // VJ# that will cast the expression for boxing.  When the VJ# team adds implicit boxing of value types, we 
                        // should remove this code.  VSWhidbey 269028
                        CodeExpression controlPropertyExpression = CodeDomUtility.BuildPropertyReferenceExpression(new CodeVariableReferenceExpression(entry.ControlID), entry.Name); 
                        if (_usingVJSCompiler) { 
                            controlPropertyExpression = CodeDomUtility.BuildJSharpCastExpression(entry.Type, controlPropertyExpression);
                        } 
                        CodeAssignStatement tableIndexAssign = new CodeAssignStatement(tableIndexer, controlPropertyExpression);

                        ifStatement.TrueStatements.Add(tableIndexAssign);
                        ifStatement.LinePragma = linePragma; 
                        currentStatements.Add(ifStatement);
                    } 
 
                    if (controlBuilder.SubBuilders.Count > 0) {
                        BuildExtractStatementsRecursive(controlBuilder.SubBuilders, statements, topLevelStatements, linePragma, tableVarName, containerVarName); 
                    }
                }
            }
 
        }
 
        /* 
         * Build the member field's declaration for a control
         */ 
        private void BuildFieldDeclaration(ControlBuilder builder) {

            // Do not generate member field for content controls.
            if (builder is System.Web.UI.WebControls.ContentBuilderInternal) { 
                return;
            } 
 
            bool hideExistingMember = false;
 
            // If we're using a non-default base class
            if (Parser.BaseType != null) {
                // Check if it has a non-private field or property that has a name that
                // matches the id of the control. 

                Type memberType = Util.GetNonPrivateFieldType(Parser.BaseType, builder.ID); 
 
                // Couldn't find a field, try a property (ASURT 45039)
                // 
                if (memberType == null)
                    memberType = Util.GetNonPrivatePropertyType(Parser.BaseType, builder.ID);

                if (memberType != null) { 

                    if (!memberType.IsAssignableFrom(builder.ControlType)) { 
 
                        if (!(typeof(Control)).IsAssignableFrom(memberType)) {
                            // If it's not a control, it's probably an unrelated member, 
                            // and we should just hide it (VSWhidbey 217135)
                            hideExistingMember = true;
                        }
                        else { 
                            throw new HttpParseException(SR.GetString(SR.Base_class_field_with_type_different_from_type_of_control,
                                builder.ID, memberType.FullName, builder.ControlType.FullName), null, 
                                builder.VirtualPath, null, builder.Line); 
                        }
                    } 
                    else {
                        // Don't build the declaration, since the base class already declares it
                        return;
                    } 
                }
            } 
 
            // Add the field.  Make it protected if the ID was declared, and private if it was generated
            CodeMemberField field = new CodeMemberField(new CodeTypeReference( 
                builder.DeclareType, CodeTypeReferenceOptions.GlobalReference), builder.ID);
            field.Attributes &= ~MemberAttributes.AccessMask;

            // If we need to hide an existing member, use 'new' (VSWhidbey 217135) 
            if (hideExistingMember)
                field.Attributes |= MemberAttributes.New; 
 
            field.LinePragma = CreateCodeLinePragma(builder);
 
            field.Attributes |= MemberAttributes.Family;

            // Set WithEvents in the UserData, so that the field will be
            // declared as WithEvents in VB (VSWhidbey 156623). 
            // But only do this if it's a Control, otherwise it may not have
            // any events (VSWhidbey 283274). 
            if (typeof(Control).IsAssignableFrom(builder.DeclareType)) { 
                field.UserData["WithEvents"] = true;
            } 

            _intermediateClass.Members.Add(field);
        }
 
        private string GetExpressionBuilderMethodName(string eventName, ControlBuilder builder) {
            return "__" + eventName + builder.ID; 
        } 

        /* 
         * Return the name of a databinding method
         */
        private string BindingMethodName(ControlBuilder builder) {
            return "__DataBind" + builder.ID; 
        }
 
        protected CodeMemberMethod BuildPropertyBindingMethod(ControlBuilder builder, bool fControlSkin) { 
            if (builder is DataBoundLiteralControlBuilder) {
                // Get the name of the databinding method 
                string methodName = BindingMethodName(builder);

                // Same linePragma in the entire method
                CodeLinePragma linePragma = CreateCodeLinePragma(builder); 

                CodeMemberMethod method = new CodeMemberMethod(); 
                method.Name = methodName; 
                method.Attributes &= ~MemberAttributes.AccessMask;
                method.Attributes |= MemberAttributes.Public; 

                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "sender"));
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(EventArgs), "e"));
 
                CodeStatementCollection topMethodStatements = new CodeStatementCollection();
                CodeStatementCollection otherMethodStatements = new CodeStatementCollection(); 
 
                // {{controlType}} target;
                CodeVariableDeclarationStatement targetDecl = new CodeVariableDeclarationStatement(builder.ControlType, "target"); 
                Type bindingContainerType = builder.BindingContainerType;

                CodeVariableDeclarationStatement containerDecl = new CodeVariableDeclarationStatement(bindingContainerType, "Container");
 
                topMethodStatements.Add(containerDecl);
                topMethodStatements.Add(targetDecl); 
 
                // target = ({{controlType}}) sender;
                CodeAssignStatement setTarget = new CodeAssignStatement(new CodeVariableReferenceExpression(targetDecl.Name), 
                                                                        new CodeCastExpression(builder.ControlType,
                                                                                               new CodeArgumentReferenceExpression("sender")));
                setTarget.LinePragma = linePragma;
                otherMethodStatements.Add(setTarget); 

                // {{containerType}} Container = ({{containerType}}) target.BindingContainer; 
                CodeAssignStatement setContainer = new CodeAssignStatement(new CodeVariableReferenceExpression(containerDecl.Name), 
                                                                           new CodeCastExpression(bindingContainerType,
                                                                                                  new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("target"), 
                                                                                                                                      "BindingContainer")));
                setContainer.LinePragma = linePragma;
                otherMethodStatements.Add(setContainer);
 
                // VSWhidbey 275175: Create the tempObjectVariable "__o" only when it's used.
                bool tempObjectVariableDeclared = false; 
 
                // If it's a DataBoundLiteralControl, call SetDataBoundString for each
                // of the databinding expressions 
                int i = -1;
                foreach (object child in builder.SubBuilders) {
                    i++;
 
                    // Ignore it if it's null
                    if (child == null) 
                        continue; 

                    // Only deal with the databinding expressions here, which have odd index 
                    if (i % 2 == 0) {
                        Debug.Assert(child is string, "child is string");
                        continue;
                    } 

                    CodeBlockBuilder codeBlock = (CodeBlockBuilder) child; 
                    Debug.Assert(codeBlock.BlockType == CodeBlockType.DataBinding); 

                    // In designer mode, generate a much simpler assignment to make 
                    // the code simpler (since it doesn't actually need to run).
                    if (_designerMode) {

                        // In designer mode, add an object variable used for simplified code expression generation 
                        if (!tempObjectVariableDeclared) {
                            tempObjectVariableDeclared = true; 
                            // object __o; 
                            topMethodStatements.Add(new CodeVariableDeclarationStatement(
                                typeof(object), tempObjectVariable)); 
                        }

                        // e.g. __o = ;
                        CodeStatement simpleAssignment = new CodeAssignStatement( 
                            new CodeVariableReferenceExpression(tempObjectVariable),
                            new CodeSnippetExpression(codeBlock.Content)); 
                        simpleAssignment.LinePragma = CreateCodeLinePragma(codeBlock); 
                        otherMethodStatements.Add(simpleAssignment);
                        continue; 
                    }

                    // e.g. target.SetDataBoundString(3, System.Convert.ToString({{codeExpr}}));
                    CodeExpression convertExpr = CodeDomUtility.GenerateConvertToString( 
                        new CodeSnippetExpression(codeBlock.Content.Trim()));
 
                    CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression( 
                        new CodeVariableReferenceExpression("target"), "SetDataBoundString");
                    methCallExpression.Parameters.Add(new CodePrimitiveExpression(i/2)); 
                    methCallExpression.Parameters.Add(convertExpr);

                    CodeStatement setDataBoundStringCall = new CodeExpressionStatement(methCallExpression);
                    setDataBoundStringCall.LinePragma = CreateCodeLinePragma(codeBlock); 
                    otherMethodStatements.Add(setDataBoundStringCall);
                } 
 
                foreach (CodeStatement stmt in topMethodStatements) {
                    method.Statements.Add(stmt); 
                }
                foreach (CodeStatement stmt in otherMethodStatements) {
                    method.Statements.Add(stmt);
                } 
                _sourceDataClass.Members.Add(method);
                return method; 
            } 
            else {
 
                EventInfo eventInfo = DataBindingExpressionBuilder.Event;

                // Same linePragma in the entire method
                CodeLinePragma linePragma = CreateCodeLinePragma(builder); 

                CodeMemberMethod method = null; 
                CodeStatementCollection topStatements = null; 
                CodeStatementCollection otherStatements = null;
 
                // Used to deal with the device filter conditionals
                CodeStatementCollection currentStmts;
                CodeStatementCollection nextStmts = null;
                PropertyEntry previous = null; 

                bool isBindableTemplateBuilder = builder is BindableTemplateBuilder; 
                bool firstEntry = true; 

                bool hasTempObject = false; 

                foreach (BoundPropertyEntry entry in builder.BoundPropertyEntries) {
                    // Skip two-way entries if it's a BindableTemplateBuilder or the two way entry is read only
                    if (entry.TwoWayBound && (isBindableTemplateBuilder || entry.ReadOnlyProperty)) 
                        continue;
 
                    // We only care about databinding entries here 
                    if (!entry.IsDataBindingEntry)
                        continue; 

                    if (firstEntry) {
                        firstEntry = false;
 
                        method = new CodeMemberMethod();
                        topStatements = new CodeStatementCollection(); 
                        otherStatements = new CodeStatementCollection(); 

                        // Get the name of the databinding method 
                        string methodName = GetExpressionBuilderMethodName(eventInfo.Name, builder);
                        method.Name = methodName;
                        method.Attributes &= ~MemberAttributes.AccessMask;
                        method.Attributes |= MemberAttributes.Public; 

                        if (_designerMode) { 
                            ApplyEditorBrowsableCustomAttribute(method); 
                        }
 
                        Type eventHandlerType = eventInfo.EventHandlerType;
                        MethodInfo mi = eventHandlerType.GetMethod("Invoke");
                        ParameterInfo[] paramInfos = mi.GetParameters();
                        foreach (ParameterInfo pi in paramInfos) { 
                            method.Parameters.Add(new CodeParameterDeclarationExpression(pi.ParameterType, pi.Name));
                        } 
 
                        nextStmts = otherStatements;
 
                        DataBindingExpressionBuilder.BuildExpressionSetup(builder, topStatements, otherStatements);

                        _sourceDataClass.Members.Add(method);
                    } 

                    currentStmts = nextStmts; 
 
                    HandleDeviceFilterConditional(ref previous, entry, otherStatements, ref currentStmts, out nextStmts);
 
                    if (entry.TwoWayBound) {
                        Debug.Assert(!entry.ReadOnlyProperty, "We should not attempt to build a data binding handler if the two way entry is read only.");
                        Debug.Assert(!entry.UseSetAttribute, "Two-way binding is not supported on expandos - this should have been prevented in ControlBuilder");
                        DataBindingExpressionBuilder.BuildEvalExpression(entry.FieldName, entry.FormatString, 
                                                                         entry.Name, entry.Type, builder, topStatements, currentStmts, linePragma, ref hasTempObject);
                    } 
                    else { 
                        DataBindingExpressionBuilder.BuildExpressionStatic(entry, builder, null, topStatements, currentStmts, linePragma, ref hasTempObject);
                    } 
                }
                if (topStatements != null) {
                    foreach (CodeStatement stmt in topStatements) {
                        method.Statements.Add(stmt); 
                    }
                } 
                if (otherStatements != null) { 
                    foreach (CodeStatement stmt in otherStatements) {
                        method.Statements.Add(stmt); 
                    }
                }
                return method;
            } 
        }
 
        /* 
         * Build the data tree for a control's render method
         */ 
        internal void BuildRenderMethod(ControlBuilder builder, bool fTemplate) {

            CodeMemberMethod method = new CodeMemberMethod();
            method.Attributes = MemberAttributes.Private | MemberAttributes.Final; 
            method.Name = "__Render" + builder.ID;
 
            if (_designerMode) { 
                ApplyEditorBrowsableCustomAttribute(method);
            } 

            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(HtmlTextWriter), renderMethodParameterName));
            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Control), "parameterContainer"));
 
            _sourceDataClass.Members.Add(method);
 
            // VSWhidbey 275175: Create the tempObjectVariable "__o" only when it's used. 
            bool tempObjectVariableDeclared = false;
 
            // Process the children if any
            if (builder.SubBuilders != null) {
                IEnumerator en = builder.SubBuilders.GetEnumerator();
 
                // Index that the control will have in its parent's Controls
                // collection. 
                // 

 

                int controlIndex = 0;

                for (int i=0; en.MoveNext(); i++) { 
                    object child = en.Current;
 
                    CodeLinePragma linePragma = null; 

                    if (child is ControlBuilder) { 
                        linePragma = CreateCodeLinePragma((ControlBuilder)child);
                    }

                    if (child is string) { 
                        if (_designerMode) continue;
 
                        AddOutputWriteStringStatement(method.Statements, (string)child); 
                    }
                    else if (child is CodeBlockBuilder) { 
                        CodeBlockBuilder codeBlockBuilder = (CodeBlockBuilder)child;

                        if (codeBlockBuilder.BlockType == CodeBlockType.Expression) {
 
                            string codeExpression = codeBlockBuilder.Content;
 
                            // In designer mode, generate a much simpler assignment to make 
                            // the code simpler (since it doesn't actually need to run).
                            if (_designerMode) { 
                                // In designer mode, add an object variable used for simplified code expression generation
                                if (!tempObjectVariableDeclared) {
                                    tempObjectVariableDeclared = true;
                                    // object __o; 
                                    method.Statements.Add(new CodeVariableDeclarationStatement(
                                        typeof(object), tempObjectVariable)); 
                                } 

                                // e.g. __o = ; 
                                CodeStatement simpleAssignment = new CodeAssignStatement(
                                    new CodeVariableReferenceExpression(tempObjectVariable),
                                    new CodeSnippetExpression(codeExpression));
                                simpleAssignment.LinePragma = linePragma; 
                                method.Statements.Add(simpleAssignment);
                                continue; 
                            } 

                            // The purpose of the following logic is to improve the debugging experience. 
                            // Basically, we gain control on the formatting of the generated line
                            // that calls output.Write, in order to try to make the call line up
                            // with the <%= ... %> block.  It's not always perfect, but it does a decent job
                            // and is always better than the v1 behavior. 

                            // Get the Write() statement codedom tree 
                            CodeStatement outputWrite = GetOutputWriteStatement( 
                                new CodeSnippetExpression(codeExpression));
 
                            // Use codedom to generate the statement as a string in the target language
                            TextWriter w = new StringWriter(CultureInfo.InvariantCulture);
                            _codeDomProvider.GenerateCodeFromStatement(outputWrite, w, null /*CodeGeneratorOptions*/);
                            string outputWriteString = w.ToString(); 

                            // The '+3' is used to make sure the generated code is positioned properly to match 
                            // the location of user code (due to the <%= %> separators). 
                            outputWriteString = outputWriteString.PadLeft(
                                codeBlockBuilder.Column + codeExpression.Length + 3); 

                            // We can then use this string as a snippet statement
                            CodeSnippetStatement lit = new CodeSnippetStatement(outputWriteString);
                            lit.LinePragma = linePragma; 
                            method.Statements.Add(lit);
                        } 
                        else { 
                            // It's a <% ... %> block
                            Debug.Assert(codeBlockBuilder.BlockType == CodeBlockType.Code); 

                            // Pad the code block so its generated offset matches the aspx
                            string code = codeBlockBuilder.Content;
                            code = code.PadLeft(code.Length + codeBlockBuilder.Column - 1); 

                            CodeSnippetStatement lit = new CodeSnippetStatement(code); 
                            lit.LinePragma = linePragma; 
                            method.Statements.Add(lit);
                        } 
                    }
                    else if (child is ControlBuilder) {

                        if (_designerMode) continue; 

                        // parameterContainer.Controls['controlIndex++'].RenderControl(output) 
                        CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); 
                        CodeExpressionStatement methodCall = new CodeExpressionStatement(methodInvoke);
                        methodInvoke.Method.TargetObject = new CodeIndexerExpression(new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression("parameterContainer"), 
                                                                                                                             "Controls"),
                                                                                         new CodeExpression[] {
                                                                                             new CodePrimitiveExpression(controlIndex++),
                                                                                         }); 
                        methodInvoke.Method.MethodName = "RenderControl";
 
                        // Don't generate a line pragma on the RenderControl call, as it degrades the 
                        // debugging experience (VSWhidbey 482416)
 
                        methodInvoke.Parameters.Add(new CodeArgumentReferenceExpression(renderMethodParameterName));
                        method.Statements.Add(methodCall);
                    }
                } 
            }
        } 
 
        protected virtual void BuildSourceDataTreeFromBuilder(ControlBuilder builder,
                                                    bool fInTemplate, bool topLevelControlInTemplate, 
                                                    PropertyEntry pse) {

            // Don't do anything for Code blocks
            if (builder is CodeBlockBuilder) 
                return;
 
            // Is the current builder for a template? 
            bool fTemplate = (builder is TemplateBuilder);
 
            // For the control name in the compiled code, we use the
            // ID if one is available (but don't use the ID inside a template)
            // Otherwise, we generate a unique name.
            if (builder.ID == null || fInTemplate) { 
                // Increase the control count to generate unique ID's
                _controlCount++; 
 
                builder.ID = "__control" + _controlCount.ToString(NumberFormatInfo.InvariantInfo);
                builder.IsGeneratedID = true; 
            }

            // Process the children
            if (builder.SubBuilders != null) { 
                foreach (object child in builder.SubBuilders) {
                    if (child is ControlBuilder) { 
                        // Do not treat it as top level control in template if the control is at top-level of a file. 
                        bool isTopLevelCtrlInTemplate =
                            fTemplate && typeof(Control).IsAssignableFrom(((ControlBuilder)child).ControlType) && !(builder is RootBuilder); 
                        BuildSourceDataTreeFromBuilder((ControlBuilder)child, fInTemplate, isTopLevelCtrlInTemplate, null);
                    }
                }
            } 

            foreach (TemplatePropertyEntry entry in builder.TemplatePropertyEntries) { 
                bool inTemplate = true; 

                // If the template container does not allow multiple instances, 
                // treat the controls as if not in templates.
                if (entry.PropertyInfo != null) {
                    TemplateInstanceAttribute templateAttrib = (TemplateInstanceAttribute)Attribute.GetCustomAttribute(entry.PropertyInfo,
                        typeof(TemplateInstanceAttribute), false /* inherit */); 
                    if (templateAttrib != null) {
                        inTemplate = (templateAttrib.Instances == TemplateInstance.Multiple); 
                    } 
                }
 
                BuildSourceDataTreeFromBuilder(((TemplatePropertyEntry)entry).Builder, inTemplate, false /*topLevelControlInTemplate*/, entry);
            }

            foreach (ComplexPropertyEntry entry in builder.ComplexPropertyEntries) { 
                // Don't create a build method for inner property strings
                if (!(entry.Builder is StringPropertyBuilder)) { 
                    BuildSourceDataTreeFromBuilder(((ComplexPropertyEntry)entry).Builder, fInTemplate, false /*topLevelControlInTemplate*/, entry); 
                }
            } 

            // Build a field declaration for the control if ID is defined on the control.
            // (Not a generated ID)
            if (!builder.IsGeneratedID) 
                BuildFieldDeclaration(builder);
 
            CodeMemberMethod buildMethod = null; 
            CodeMemberMethod dataBindingMethod = null;
 
            // Skip the rest if we're only generating the intermediate class
            if (_sourceDataClass != null) {

                if (!_designerMode) { 
                    // Build a Build method for the control
                    buildMethod = BuildBuildMethod(builder, fTemplate, fInTemplate, topLevelControlInTemplate, pse, false); 
                } 

                // Build a Render method for the control, unless it has no code 
                if (builder.HasAspCode) {
                    BuildRenderMethod(builder, fTemplate);
                }
 
                // Build a method to extract values from the template
                BuildExtractMethod(builder); 
 
                // Build a property binding method for the control
                dataBindingMethod = BuildPropertyBindingMethod(builder, false); 
            }

            // Give the ControlBuilder a chance to look at and modify the tree
            builder.ProcessGeneratedCode(_codeCompileUnit, _intermediateClass, 
                _sourceDataClass, buildMethod, dataBindingMethod);
        } 
 
        internal virtual CodeExpression BuildStringPropertyExpression(PropertyEntry pse) {
            string value = String.Empty; 
            if (pse is SimplePropertyEntry) {
                value = (string)((SimplePropertyEntry)pse).Value;
            }
            else { 
                Debug.Assert(pse is ComplexPropertyEntry);
                ComplexPropertyEntry cpe = (ComplexPropertyEntry)pse; 
                value = (string)((StringPropertyBuilder)cpe.Builder).BuildObject(); 
            }
 
            return CodeDomUtility.GenerateExpressionForValue(pse.PropertyInfo, value, typeof(string));
        }

        protected virtual CodeAssignStatement BuildTemplatePropertyStatement(CodeExpression ctrlRefExpr) { 

            // e.g. __ctrl.TemplateControl = this; 
            CodeAssignStatement assign = new CodeAssignStatement(); 
            assign.Left = new CodePropertyReferenceExpression(ctrlRefExpr, "TemplateControl");
            assign.Right = new CodeThisReferenceExpression(); 
            return assign;
        }

        /* 
         * Return the name of an extract method
         */ 
        private string ExtractMethodName(ControlBuilder builder) { 
            return extractTemplateValuesMethodPrefix + builder.ID;
        } 


        private Type GetCtrlTypeForBuilder(ControlBuilder builder, bool fTemplate) {
 
            if (builder is RootBuilder && builder.ControlType != null)
                return builder.ControlType; 
 
            if (fTemplate)
                return typeof(Control); 

            return builder.ControlType;
        }
 
        protected string GetMethodNameForBuilder(string prefix, ControlBuilder builder) {
            if (builder is RootBuilder) { 
                return prefix + "Tree"; 
            }
            else { 
                return prefix + builder.ID;
            }
        }
 
        /*
         * Helper method to generate the device filter conditionals.  e.g. 
         *   if (this.TestDeviceFilter("FilterName")) { 
         *       // ...
         *   } 
         *   else {
         *       // ...
         *   }
         */ 
        private void HandleDeviceFilterConditional(
            ref PropertyEntry previous, PropertyEntry current, 
            CodeStatementCollection topStmts, 
            ref CodeStatementCollection currentStmts,
            out CodeStatementCollection nextStmts) { 

            bool sameAsPrevious = (previous != null) && StringUtil.EqualsIgnoreCase(previous.Name, current.Name);

            if (current.Filter.Length != 0) { 
                if (!sameAsPrevious) {
                    // If the current property entry is not the same as the previous entries, 
                    // we need to start a new block of code 
                    currentStmts = topStmts;
                    previous = null; 
                }

                CodeConditionStatement ifStmt = new CodeConditionStatement();
                CodeMethodInvokeExpression methCallExpression = new CodeMethodInvokeExpression( 
                    new CodeThisReferenceExpression(), "TestDeviceFilter");
                methCallExpression.Parameters.Add(new CodePrimitiveExpression(current.Filter)); 
                ifStmt.Condition = methCallExpression; 
                currentStmts.Add(ifStmt);
 
                // The current entry needs to go in the 'if' clause
                currentStmts = ifStmt.TrueStatements;

                // The next entry will tentatively go in the 'else' clause, unless it is 
                // for a different property (which we would catch next time around)
                nextStmts = ifStmt.FalseStatements; 
 
                previous = current;
            } 
            else {
                // If we're switching to a new property, we need to add to the top-level statements (not the false block of an if)
                if (!sameAsPrevious) {
                    currentStmts = topStmts; 
                }
                nextStmts = topStmts; 
                previous = null; 
            }
        } 

        protected virtual bool UseResourceLiteralString(string s) {

            // If the string is long enough, and the compiler supports it, use a UTF8 resource 
            // string for performance
            return (s.Length >= minLongLiteralStringLength && _codeDomProvider.Supports(GeneratorSupport.Win32Resources)); 
        } 
    }
} 

// 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