New tests.
[mono.git] / mcs / class / System.Web / System.Web.Compilation / TemplateControlCompiler.cs
index 52557d2d0f5a3509f2dec4adb2cd5255b36f3f12..4b01ccd67853f2ae263f23f390a1cc351188cde5 100644 (file)
@@ -32,22 +32,21 @@ using System;
 using System.CodeDom;
 using System.Collections;
 using System.ComponentModel;
+using System.Configuration;
+using System.Collections.Specialized;
+using System.Collections.Generic;
 using System.Drawing;
 using System.Globalization;
 using System.Reflection;
+using System.Resources;
 using System.Text;
 using System.Web;
+using System.Web.Configuration;
 using System.Web.UI;
 using System.Web.UI.WebControls;
 using System.Web.Util;
 using System.ComponentModel.Design.Serialization;
 using System.Text.RegularExpressions;
-#if NET_2_0
-using System.Configuration;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Web.Configuration;
-#endif
 
 namespace System.Web.Compilation
 {
@@ -65,16 +64,14 @@ namespace System.Web.Compilation
 
                internal static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
                
-#if NET_2_0
                List <string> masterPageContentPlaceHolders;
+               static Regex startsWithBindRegex = new Regex (@"^Bind\s*\(", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                // When modifying those, make sure to look at the SanitizeBindCall to make sure it
                // picks up correct groups.
                static Regex bindRegex = new Regex (@"Bind\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)\s*%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                static Regex bindRegexInValue = new Regex (@"Bind\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
-#endif
                static Regex evalRegexInValue = new Regex (@"(.*)Eval\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)(.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
 
-#if NET_2_0
                List <string> MasterPageContentPlaceHolders {
                        get {
                                if (masterPageContentPlaceHolders == null)
@@ -82,7 +79,7 @@ namespace System.Web.Compilation
                                return masterPageContentPlaceHolders;
                        }
                }
-#endif
+
                public TemplateControlCompiler (TemplateControlParser parser)
                        : base (parser)
                {
@@ -99,10 +96,9 @@ namespace System.Web.Compilation
                {
                        if (builder == null || builder.ID == null || builder.ControlType == null)
                                return;
-#if NET_2_0
+
                        if (partialNameOverride [builder.ID] != null)
                                return;
-#endif
 
                        MemberAttributes ma = MemberAttributes.Family;
                        currentLocation = builder.Location;
@@ -112,13 +108,11 @@ namespace System.Web.Compilation
                        CodeMemberField field;
                        field = new CodeMemberField (builder.ControlType.FullName, builder.ID);
                        field.Attributes = ma;
-#if NET_2_0
                        field.Type.Options |= CodeTypeReferenceOptions.GlobalReference;
 
                        if (partialClass != null)
                                partialClass.Members.Add (AddLinePragma (field, builder));
                        else
-#endif
                                mainClass.Members.Add (AddLinePragma (field, builder));
                }
 
@@ -142,15 +136,8 @@ namespace System.Web.Compilation
                                return false;
 
                        if (!other.IsAssignableFrom (type)) {
-#if NET_2_0
                                ma |= MemberAttributes.New;
                                return false;
-#else
-                               string msg = String.Format ("The base class includes the field '{0}', but its " +
-                                                           "type '{1}' is not compatible with {2}",
-                                                           id, other, type);
-                               throw new ParseException (currentLocation, msg);
-#endif
                        }
 
                        return true;
@@ -190,9 +177,7 @@ namespace System.Web.Compilation
                         * method, allow subclasses to insert control
                         * specific code. */
                        if (builder is RootBuilder) {
-#if NET_2_0
                                SetCustomAttributes (method);
-#endif
                                AddStatementsToInitMethod (method);
                        }
                        
@@ -270,7 +255,6 @@ namespace System.Web.Compilation
                                        method.Statements.Add (initAsControl);
                                }
 
-#if NET_2_0
                                if (builder.ParentTemplateBuilder is System.Web.UI.WebControls.ContentBuilderInternal) {
                                        PropertyInfo pi;
 
@@ -311,7 +295,6 @@ namespace System.Web.Compilation
                                                applyStyleSheetSkin.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page"));
                                        method.Statements.Add (applyStyleSheetSkin);
                                }
-#endif
 
                                // Process template children before anything else
                                ProcessTemplateChildren (builder);
@@ -322,9 +305,7 @@ namespace System.Web.Compilation
                                string ctl_id = builder.GetAttribute ("id");
                                if (ctl_id != null && ctl_id.Length != 0)
                                        CreateAssignStatementFromAttribute (builder, "id");
-
                                
-#if NET_2_0
                                if (typeof (ContentPlaceHolder).IsAssignableFrom (type)) {
                                        List <string> placeHolderIds = MasterPageContentPlaceHolders;
                                        string cphID = builder.ID;
@@ -393,7 +374,6 @@ namespace System.Web.Compilation
                                        // this is the bit that causes the following stuff to end up in the else { }
                                        builder.MethodStatements = condStatement.FalseStatements;
                                }
-#endif
                        }
                        
                        mainClass.Members.Add (method);
@@ -405,18 +385,15 @@ namespace System.Web.Compilation
                        if (templates != null && templates.Count > 0) {
                                foreach (TemplateBuilder tb in templates) {
                                        CreateControlTree (tb, true, false);
-#if NET_2_0
                                        if (tb.BindingDirection == BindingDirection.TwoWay) {
                                                string extractMethod = CreateExtractValuesMethod (tb);
                                                AddBindableTemplateInvocation (builder, tb.TagName, tb.Method.Name, extractMethod);
                                        } else
-#endif
                                                AddTemplateInvocation (builder, tb.TagName, tb.Method.Name);
                                }
                        }
                }
                
-#if NET_2_0
                void SetCustomAttribute (CodeMemberMethod method, UnknownAttributeDescriptor uad)
                {
                        CodeAssignStatement assign = new CodeAssignStatement ();
@@ -441,7 +418,6 @@ namespace System.Web.Compilation
                        foreach (UnknownAttributeDescriptor uad in attrs)
                                SetCustomAttribute (method, uad);
                }
-#endif
                
                protected virtual void AddStatementsToInitMethod (CodeMemberMethod method)
                {
@@ -481,10 +457,8 @@ namespace System.Web.Compilation
                {
                        Match match = regex.Match (value);
                        if (!match.Success) {
-#if NET_2_0
                                if (isBind)
                                        throw new HttpParseException ("Bind invocation wasn't formatted properly.");
-#endif
                                return null;
                        }
                        
@@ -520,14 +494,12 @@ namespace System.Web.Compilation
                        CodeExpression valueExpression = null;
                        value = value.Trim ();
                        
-#if NET_2_0
                        bool need_if = false;
-                       if (StrUtils.StartsWith (value, "Bind", true)) {
+                       if (startsWithBindRegex.Match (value).Success) {
                                valueExpression = CreateEvalInvokeExpression (bindRegexInValue, value, true);
                                if (valueExpression != null)
                                        need_if = true;
                        } else
-#endif
                                if (StrUtils.StartsWith (value, "Eval", true))
                                        valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false);
                        
@@ -535,7 +507,6 @@ namespace System.Web.Compilation
                                valueExpression = new CodeSnippetExpression (value);
                        
                        method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), builder.ControlType);
-                       
                        CodeVariableReferenceExpression targetExpr = new CodeVariableReferenceExpression ("target");
 
                        // This should be a CodePropertyReferenceExpression for properties... but it works anyway
@@ -552,16 +523,13 @@ namespace System.Web.Compilation
                                expr = new CodeCastExpression (type, valueExpression);
 
                        CodeAssignStatement assign = new CodeAssignStatement (field, expr);
-#if NET_2_0
                        if (need_if) {
                                CodeExpression page = new CodePropertyReferenceExpression (thisRef, "Page");
                                CodeExpression left = new CodeMethodInvokeExpression (page, "GetDataItem");
                                CodeBinaryOperatorExpression ce = new CodeBinaryOperatorExpression (left, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null));
                                CodeConditionStatement ccs = new CodeConditionStatement (ce, assign);
                                method.Statements.Add (ccs);
-                       }
-                       else
-#endif
+                       } else
                                method.Statements.Add (assign);
 
                        mainClass.Members.Add (method);
@@ -577,13 +545,10 @@ namespace System.Web.Compilation
                                string dbMethodName = DataBoundProperty (builder, type, var_name, att);
                                AddEventAssign (method, builder, "DataBinding", typeof (EventHandler), dbMethodName);
                                return;
-                       }
-#if NET_2_0
-                       else if (isExpression && isWritable) {
+                       } else if (isExpression && isWritable) {
                                AddExpressionAssign (method, builder, member, type, var_name, att);
                                return;
                        }
-#endif
 
                        CodeAssignStatement assign = new CodeAssignStatement ();
                        assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
@@ -624,7 +589,6 @@ namespace System.Web.Compilation
                        return IsDirective (value, '#');
                }
 
-#if NET_2_0
                bool IsExpression (string value)
                {
                        return IsDirective (value, '$');
@@ -653,18 +617,17 @@ namespace System.Web.Compilation
                                }
                        }
                }
-#endif
 
                /*
                static bool InvariantCompare (string a, string b)
                {
-                       return (0 == String.Compare (a, b, false, CultureInfo.InvariantCulture));
+                       return (0 == String.Compare (a, b, false, Helpers.InvariantCulture));
                }
                */
 
                static bool InvariantCompareNoCase (string a, string b)
                {
-                       return (0 == String.Compare (a, b, true, CultureInfo.InvariantCulture));
+                       return (0 == String.Compare (a, b, true, Helpers.InvariantCulture));
                }
 
                static MemberInfo GetFieldOrProperty (Type type, string name)
@@ -701,11 +664,7 @@ namespace System.Web.Compilation
                        int hyphen = id.IndexOf ('-');
                        bool isPropertyInfo = (member is PropertyInfo);
                        bool isDataBound = IsDataBound (attValue);
-#if NET_2_0
                        bool isExpression = !isDataBound && IsExpression (attValue);
-#else
-                       bool isExpression = false;
-#endif
                        Type type;
                        if (isPropertyInfo) {
                                type = ((PropertyInfo) member).PropertyType;
@@ -714,11 +673,9 @@ namespace System.Web.Compilation
                        }
 
                        if (InvariantCompareNoCase (member.Name, id)) {
-#if NET_2_0
                                if (isDataBound)
-                                       RegisterBindingInfo (builder, member.Name, ref attValue);
-                               
-#endif
+                                       RegisterBindingInfo (builder, member.Name, ref attValue);                               
+
                                if (!IsWritablePropertyOrField (member))
                                        return false;
                                
@@ -761,10 +718,10 @@ namespace System.Web.Compilation
                        string val = attValue;
                        if (attValue == null && is_bool)
                                val = "true"; // Font-Bold <=> Font-Bold="true"
-#if NET_2_0
+
                        if (isDataBound)
                                RegisterBindingInfo (builder, prefix + member.Name + "." + subprop.Name, ref attValue);
-#endif
+
                        AddCodeForPropertyOrField (builder, subprop.PropertyType,
                                                   prefix + member.Name + "." + subprop.Name,
                                                   val, subprop, isDataBound, isExpression);
@@ -772,7 +729,6 @@ namespace System.Web.Compilation
                        return true;
                }
 
-#if NET_2_0
                CodeExpression CompileExpression (MemberInfo member, Type type, string value, bool useSetAttribute)
                {
                        // First let's find the correct expression builder
@@ -783,11 +739,7 @@ namespace System.Web.Compilation
                        string prefix = value.Substring (0, colon).Trim ();
                        string expr = value.Substring (colon + 1).Trim ();
                        
-                       System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration ("");
-                       if (config == null)
-                               return null;
-                       
-                       CompilationSection cs = (CompilationSection)config.GetSection ("system.web/compilation");
+                       CompilationSection cs = (CompilationSection)WebConfigurationManager.GetWebApplicationSection ("system.web/compilation");
                        if (cs == null)
                                return null;
                        
@@ -855,6 +807,36 @@ namespace System.Web.Compilation
                        
                        return ret;
                }
+
+               bool ResourceProviderHasObject (string key)
+               {
+                       IResourceProvider rp = HttpContext.GetResourceProvider (InputVirtualPath.Absolute, true);
+                       if (rp == null)
+                               return false;
+
+                       IResourceReader rr = rp.ResourceReader;
+                       if (rr == null)
+                               return false;
+
+                       try {
+                               IDictionaryEnumerator ide = rr.GetEnumerator ();
+                               if (ide == null)
+                                       return false;
+                       
+                               string dictKey;
+                               while (ide.MoveNext ()) {
+                                       dictKey = ide.Key as string;
+                                       if (String.IsNullOrEmpty (dictKey))
+                                               continue;
+                                       if (String.Compare (key, dictKey, StringComparison.Ordinal) == 0)
+                                               return true;
+                               }
+                       } finally {
+                               rr.Close ();
+                       }
+                       
+                       return false;
+               }
                
                void AssignPropertyFromResources (ControlBuilder builder, MemberInfo mi, string attvalue)
                {
@@ -864,9 +846,16 @@ namespace System.Web.Compilation
                        if (!isProperty && !isField || !IsWritablePropertyOrField (mi))
                                return;                 
 
+                       object[] attrs = mi.GetCustomAttributes (typeof (LocalizableAttribute), true);
+                       if (attrs != null && attrs.Length > 0 && !((LocalizableAttribute)attrs [0]).IsLocalizable)
+                               return;
+                       
                        string memberName = mi.Name;
                        string resname = String.Concat (attvalue, ".", memberName);
 
+                       if (!ResourceProviderHasObject (resname))
+                               return;
+                       
                        // __ctrl.Text = System.Convert.ToString(HttpContext.GetLocalResourceObject("ButtonResource1.Text"));
                        string inputFile = parser.InputFile;
                        string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
@@ -923,7 +912,6 @@ namespace System.Web.Compilation
 
                        AssignPropertiesFromResources (builder, controlType, attvalue);
                }
-#endif
                
                void AddEventAssign (CodeMemberMethod method, ControlBuilder builder, string name, Type type, string value)
                {
@@ -943,7 +931,7 @@ namespace System.Web.Compilation
                        Type type = builder.ControlType;
                        
                        string attvalue = builder.GetAttribute (id);
-                       if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
+                       if (id.Length > 2 && String.Compare (id.Substring (0, 2), "ON", true, Helpers.InvariantCulture) == 0){
                                if (ev_info == null)
                                        ev_info = type.GetEvents ();
 
@@ -962,12 +950,10 @@ namespace System.Web.Compilation
 
                        }
 
-#if NET_2_0
-                       if (id.ToLower () == "meta:resourcekey") {
+                       if (String.Compare (id, "meta:resourcekey", StringComparison.OrdinalIgnoreCase) == 0) {
                                AssignPropertiesFromResources (builder, attvalue);
                                return;
                        }
-#endif
                        
                        int hyphen = id.IndexOf ('-');
                        string alt_id = id;
@@ -985,20 +971,16 @@ namespace System.Web.Compilation
 
                        CodeMemberMethod method = builder.Method;
                        bool isDatabound = IsDataBound (attvalue);
-#if NET_2_0
                        bool isExpression = !isDatabound && IsExpression (attvalue);
-#endif
 
                        if (isDatabound) {
                                string value = attvalue.Substring (3, attvalue.Length - 5).Trim ();
                                CodeExpression valueExpression = null;
-#if NET_2_0
-                               if (StrUtils.StartsWith (value, "Bind", true))
+                               if (startsWithBindRegex.Match (value).Success)
                                        valueExpression = CreateEvalInvokeExpression (bindRegexInValue, value, true);
                                else
-#endif
-                               if (StrUtils.StartsWith (value, "Eval", true))
-                                       valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false);
+                                       if (StrUtils.StartsWith (value, "Eval", true))
+                                               valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false);
                                
                                if (valueExpression == null && value != null && value.Trim () != String.Empty)
                                        valueExpression = new CodeSnippetExpression (value);
@@ -1015,12 +997,10 @@ namespace System.Web.Compilation
                                expr.Parameters.Add (new CodePrimitiveExpression (id));
 
                                CodeExpression valueExpr = null;
-#if NET_2_0
                                if (isExpression)
                                        valueExpr = CompileExpression (null, typeof (string), attvalue, true);
 
                                if (valueExpr == null)
-#endif
                                        valueExpr = new CodePrimitiveExpression (attvalue);
                                
                                expr.Parameters.Add (valueExpr);
@@ -1040,16 +1020,14 @@ namespace System.Web.Compilation
                                        continue;
                                // ID is assigned in BuildControltree
                                if (InvariantCompareNoCase (id, "id"))
-                                       continue;
-                               
-#if NET_2_0
+                                       continue;                               
+
                                /* we skip SkinID here as it's assigned in BuildControlTree */
                                if (InvariantCompareNoCase (id, "skinid"))
                                        continue;
                                if (InvariantCompareNoCase (id, "meta:resourcekey"))
                                        continue; // ignore, this one's processed at the very end of
                                                  // the method
-#endif
                                CreateAssignStatementFromAttribute (builder, id);
                        }
                }
@@ -1065,6 +1043,8 @@ namespace System.Web.Compilation
                        AddEventAssign (method, builder, "DataBinding", typeof (EventHandler), dbMethodName);
 
                        method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), builder.ControlType);
+                       builder.DataBindingMethod = method;
+
                        CodeCastExpression cast;
                        CodeMethodReferenceExpression methodExpr;
                        CodeMethodInvokeExpression expr;
@@ -1173,7 +1153,6 @@ namespace System.Web.Compilation
                        builder.Method.Statements.Add (AddLinePragma (assign, builder));
                }
 
-#if NET_2_0
                void AddBindableTemplateInvocation (ControlBuilder builder, string name, string methodName, string extractMethodName)
                {
                        CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
@@ -1266,7 +1245,6 @@ namespace System.Web.Compilation
 
                        method.Statements.Add (AddLinePragma (invoke, cbuilder));
                }
-#endif
 
                void AddCodeRender (ControlBuilder parent, CodeRenderBuilder cr)
                {
@@ -1284,49 +1262,25 @@ namespace System.Web.Compilation
                                                        new CodeArgumentReferenceExpression ("__output"),
                                                        "Write");
 
-                       expr.Parameters.Add (new CodeSnippetExpression (cr.Code));
+                       expr.Parameters.Add (GetWrappedCodeExpression (cr));
                        parent.RenderMethod.Statements.Add (AddLinePragma (expr, cr));
                }
 
-               static PropertyInfo GetContainerProperty (Type type, string[] propNames)
+               CodeExpression GetWrappedCodeExpression (CodeRenderBuilder cr)
                {
-                       PropertyInfo prop;
-                       
-                       foreach (string name in propNames) {
-                               prop = type.GetProperty (name, noCaseFlags & ~BindingFlags.NonPublic);
-                               if (prop != null)
-                                       return prop;
-                       }
-
-                       return null;
-               }
-
-#if !NET_2_0
-               static string[] containerPropNames = {"Items", "Rows"};
+                       var ret = new CodeSnippetExpression (cr.Code);
+#if NET_4_0
+                       if (cr.HtmlEncode) {
+                               var encodeRef = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (typeof (HttpUtility)), "HtmlEncode");
+                               return new CodeMethodInvokeExpression (encodeRef, new CodeExpression[] { ret });
+                       } else
 #endif
+                               return ret;
+               }
                
                static Type GetContainerType (ControlBuilder builder)
                {
-                       Type type = builder.BindingContainerType;
-                       
-#if NET_2_0
-                       return type;
-#else
-                       
-                       PropertyInfo prop = GetContainerProperty (type, containerPropNames);
-                       if (prop == null)
-                               return type;
-
-                       Type ptype = prop.PropertyType;
-                       if (!typeof (ICollection).IsAssignableFrom (ptype))
-                               return type;
-
-                       prop = ptype.GetProperty ("Item", noCaseFlags & ~BindingFlags.NonPublic);
-                       if (prop == null)
-                               return type;
-
-                       return prop.PropertyType;
-#endif
+                       return builder.BindingContainerType;
                }
                
                CodeMemberMethod CreateDBMethod (ControlBuilder builder, string name, Type container, Type target)
@@ -1382,6 +1336,7 @@ namespace System.Web.Compilation
 
                        // Add the DataBind handler
                        method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), typeof (DataBoundLiteralControl));
+                       builder.DataBindingMethod = method;
 
                        CodeVariableReferenceExpression targetExpr = new CodeVariableReferenceExpression ("target");
                        CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
@@ -1397,7 +1352,7 @@ namespace System.Web.Compilation
                        method.Statements.Add (AddLinePragma (invoke, builder));
                        
                        mainClass.Members.Add (method);
-
+                       
                        AddChildCall (builder, db);
                }
 
@@ -1417,9 +1372,7 @@ namespace System.Web.Compilation
                        if (!isTemplate && !inTemplate) {
                                CreateField (builder, true);
                        } else if (!isTemplate) {
-                               bool doCheck = false;
-                               
-#if NET_2_0
+                               bool doCheck = false;                           
                                bool singleInstance = false;
                                ControlBuilder pb = builder.ParentBuilder;
                                TemplateBuilder tpb;
@@ -1436,12 +1389,10 @@ namespace System.Web.Compilation
                                }
                                
                                if (!singleInstance)
-#endif
                                        builder.ID = builder.GetNextID (null);
-#if NET_2_0
                                else
                                        doCheck = true;
-#endif
+
                                CreateField (builder, doCheck);
                        }
 
@@ -1460,11 +1411,8 @@ namespace System.Web.Compilation
                                        FlushText (builder, sb);
                                        if (b is ObjectTagBuilder) {
                                                ProcessObjectTag ((ObjectTagBuilder) b);
-                                               continue;
-                                       }
-
-                                       StringPropertyBuilder pb = b as StringPropertyBuilder;
-                                       if (pb != null){
+                                       } else if (b is StringPropertyBuilder) {
+                                               StringPropertyBuilder pb = b as StringPropertyBuilder;
                                                if (pb.Children != null && pb.Children.Count > 0) {
                                                        StringBuilder asb = new StringBuilder ();
                                                        foreach (string s in pb.Children)
@@ -1475,45 +1423,34 @@ namespace System.Web.Compilation
                                                        assign.Right = new CodePrimitiveExpression (asb.ToString ());
                                                        method.Statements.Add (AddLinePragma (assign, builder));
                                                }
-                                               continue;
-                                       }
-
-#if NET_2_0
-                                       if (b is ContentBuilderInternal) {
+                                       } else if (b is ContentBuilderInternal) {
                                                ContentBuilderInternal cb = (ContentBuilderInternal) b;
                                                CreateControlTree (cb, false, true);
                                                AddContentTemplateInvocation (cb, builder.Method, cb.Method.Name);
                                                continue;
                                        }
-#endif
-                                       // Ignore TemplateBuilders - they are processed in InitMethod
-                                       if (b is TemplateBuilder)
-                                               continue;
 
-                                       if (b is CodeRenderBuilder) {
+                                       // Ignore TemplateBuilders - they are processed in InitMethod
+                                       else if (b is TemplateBuilder) {
+                                       } else if (b is CodeRenderBuilder) {
                                                AddCodeRender (builder, (CodeRenderBuilder) b);
-                                               continue;
-                                       }
-
-                                       if (b is DataBindingBuilder) {
+                                       } else if (b is DataBindingBuilder) {
                                                AddDataBindingLiteral (builder, (DataBindingBuilder) b);
-                                               continue;
-                                       }
-                                       
-                                       if (b is ControlBuilder) {
+                                       } else if (b is ControlBuilder) {
                                                ControlBuilder child = (ControlBuilder) b;
                                                CreateControlTree (child, inTemplate, builder.ChildrenAsProperties);
                                                AddChildCall (builder, child);
                                                continue;
-                                       }
+                                       } else
+                                               throw new Exception ("???");
 
-                                       throw new Exception ("???");
+                                       ControlBuilder bldr = b as ControlBuilder;
+                                       bldr.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, bldr.Method, bldr.DataBindingMethod);
                                }
 
                                FlushText (builder, sb);
                        }
 
-
                        ControlBuilder defaultPropertyBuilder = builder.DefaultPropertyBuilder;
                        if (defaultPropertyBuilder != null) {
                                CreateControlTree (defaultPropertyBuilder, false, true);
@@ -1538,20 +1475,19 @@ namespace System.Web.Compilation
                                builder.MethodStatements.Add (invoke);
                        }
 
-#if NET_2_0
                        if (builder is RootBuilder)
                                if (!String.IsNullOrEmpty (parser.MetaResourceKey))
                                        AssignPropertiesFromResources (builder, parser.BaseType, parser.MetaResourceKey);
                        
                        if ((!isTemplate || builder is RootBuilder) && !String.IsNullOrEmpty (builder.GetAttribute ("meta:resourcekey")))
                                CreateAssignStatementFromAttribute (builder, "meta:resourcekey");
-#endif
 
                        if (!childrenAsProperties && typeof (Control).IsAssignableFrom (builder.ControlType))
                                builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+
+                       builder.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, builder.Method, builder.DataBindingMethod);
                }
 
-#if NET_2_0
                protected override void AddStatementsToConstructor (CodeConstructor ctor)
                {
                        if (masterPageContentPlaceHolders == null || masterPageContentPlaceHolders.Count == 0)
@@ -1569,11 +1505,10 @@ namespace System.Web.Compilation
                        CodeMethodInvokeExpression mcall;
                        foreach (string id in masterPageContentPlaceHolders) {
                                mcall = new CodeMethodInvokeExpression (ilistRef, "Add");
-                               mcall.Parameters.Add (new CodePrimitiveExpression (id));
+                               mcall.Parameters.Add (new CodePrimitiveExpression (id.ToLowerInvariant ()));
                                statements.Add (mcall);
                        }
                }
-#endif
                
                protected internal override void CreateMethods ()
                {
@@ -1584,7 +1519,6 @@ namespace System.Web.Compilation
                        CreateFrameworkInitializeMethod ();
                }
 
-#if NET_2_0
                protected override void InitializeType ()
                {
                        List <string> registeredTagNames = parser.RegisteredTagNames;
@@ -1609,7 +1543,6 @@ namespace System.Web.Compilation
                        CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (baseRef, "FrameworkInitialize");
                        method.Statements.Add (invoke);
                }
-#endif
                
                void CallSetStringResourcePointer (CodeMemberMethod method)
                {
@@ -1628,9 +1561,7 @@ namespace System.Web.Compilation
                        method.Name = "FrameworkInitialize";
                        method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
                        PrependStatementsToFrameworkInitialize (method);
-#if NET_2_0
                        CallBaseFrameworkInitialize (method);
-#endif
                        CallSetStringResourcePointer (method);
                        AppendStatementsToFrameworkInitialize (method);
                        mainClass.Members.Add (method);
@@ -1708,15 +1639,12 @@ namespace System.Web.Compilation
 
                        CodeCastExpression cast = new CodeCastExpression (appType.FullName, propRef);
                        prop.GetStatements.Add (new CodeMethodReturnStatement (cast));
-#if NET_2_0
                        if (partialClass != null)
                                partialClass.Members.Add (prop);
                        else
-#endif
-                       mainClass.Members.Add (prop);
+                               mainClass.Members.Add (prop);
                }
 
-#if NET_2_0
                void CreateContentPlaceHolderTemplateProperty (string backingField, string name)
                {
                        CodeMemberProperty prop = new CodeMemberProperty ();
@@ -1745,7 +1673,6 @@ namespace System.Web.Compilation
 
                        mainClass.Members.Add (prop);
                }
-#endif
                
                void CreateAutoHandlers ()
                {
@@ -1762,11 +1689,8 @@ namespace System.Web.Compilation
                        prop.GetStatements.Add (ret);
                        prop.SetStatements.Add (new CodeAssignStatement (fldRef, new CodePropertySetValueReferenceExpression ()));
 
-#if NET_2_0
                        CodeAttributeDeclaration attr = new CodeAttributeDeclaration ("System.Obsolete");
-                       prop.CustomAttributes.Add (attr);
-#endif
-                       
+                       prop.CustomAttributes.Add (attr);                       
                        mainClass.Members.Add (prop);
 
                        // Add the __autoHandlers field
@@ -1786,66 +1710,36 @@ namespace System.Web.Compilation
                        mainClass.Members.Add (prop);
                }
 
-#if NET_2_0
                protected virtual string HandleUrlProperty (string str, MemberInfo member)
                {
                        return str;
                }
-#endif
 
                TypeConverter GetConverterForMember (MemberInfo member)
                {
-                       TypeConverterAttribute tca = null;
-                       object[] attrs;
-                       
-#if NET_2_0
-                       attrs = member.GetCustomAttributes (typeof (TypeConverterAttribute), true);
-                       if (attrs.Length > 0)
-                               tca = attrs [0] as TypeConverterAttribute;
-#else
-                       attrs = member.GetCustomAttributes (true);
-                       
-                       foreach (object attr in attrs) {
-                               tca = attr as TypeConverterAttribute;
-                               
-                               if (tca != null)
-                                       break;
-                       }
-#endif
-
-                       if (tca == null)
+                       TypeDescriptionProvider prov = TypeDescriptor.GetProvider (member.ReflectedType);
+                       if (prov == null)
                                return null;
 
-                       string typeName = tca.ConverterTypeName;
-                       if (typeName == null || typeName.Length == 0)
-                               return null;
+                       ICustomTypeDescriptor desc = prov.GetTypeDescriptor (member.ReflectedType);
+                       PropertyDescriptorCollection coll = desc != null ? desc.GetProperties () : null;
 
-                       Type t = null;
-                       try {
-                               t = HttpApplication.LoadType (typeName);
-                       } catch (Exception) {
-                               // ignore
-                       }
+                       if (coll == null || coll.Count == 0)
+                               return null;
 
-                       if (t == null)
+                       PropertyDescriptor pd = coll.Find (member.Name, false);
+                       if (pd == null)
                                return null;
 
-                       return (TypeConverter) Activator.CreateInstance (t);
+                       return pd.Converter;
                }
                
                CodeExpression CreateNullableExpression (Type type, CodeExpression inst, bool nullable)
                {
-#if NET_2_0
                        if (!nullable)
                                return inst;
                        
-                       return new CodeObjectCreateExpression (
-                               type,
-                               new CodeExpression[] {inst}
-                       );
-#else
-                       return inst;
-#endif
+                       return new CodeObjectCreateExpression (type, new CodeExpression[] {inst});
                }
 
                bool SafeCanConvertFrom (Type type, TypeConverter cvt)
@@ -1884,25 +1778,23 @@ namespace System.Web.Compilation
 
                        bool wasNullable = false;
                        Type originalType = type;
-#if NET_2_0
+
                        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {
                                Type[] types = type.GetGenericArguments();
                                originalType = type;
                                type = types[0]; // we're interested only in the first type here
                                wasNullable = true;
                        }
-#endif
+
                        if (type == typeof (string)) {
-                               if (preConverted)
+                               object[] urlAttr = member.GetCustomAttributes (typeof (UrlPropertyAttribute), true);
+                               if (urlAttr.Length != 0)
+                                       str = HandleUrlProperty ((preConverted && convertedFromAttr is string) ? (string)convertedFromAttr : str, member);
+                               else if (preConverted)
                                        return CreateNullableExpression (originalType,
                                                                         new CodePrimitiveExpression ((string) convertedFromAttr),
                                                                         wasNullable);
-                               
-#if NET_2_0
-                               object[] urlAttr = member.GetCustomAttributes (typeof (UrlPropertyAttribute), true);
-                               if (urlAttr.Length != 0)
-                                       str = HandleUrlProperty (str, member);
-#endif
+
                                return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
                        } else if (type == typeof (bool)) {
                                if (preConverted)
@@ -1914,10 +1806,8 @@ namespace System.Web.Compilation
                                        return CreateNullableExpression (originalType, new CodePrimitiveExpression (true), wasNullable);
                                else if (InvariantCompareNoCase (str, "false"))
                                        return CreateNullableExpression (originalType, new CodePrimitiveExpression (false), wasNullable);
-#if NET_2_0
                                else if (wasNullable && InvariantCompareNoCase(str, "null"))
                                        return new CodePrimitiveExpression (null);
-#endif
                                else
                                        throw new ParseException (currentLocation,
                                                        "Value '" + str  + "' is not a valid boolean.");
@@ -1931,7 +1821,7 @@ namespace System.Web.Compilation
                                return CreateNullableExpression (originalType,
                                                                 new CodePrimitiveExpression (
                                                                         Convert.ChangeType (preConverted ? convertedFromAttr : str,
-                                                                                            type, CultureInfo.InvariantCulture)),
+                                                                                            type, Helpers.InvariantCulture)),
                                                                 wasNullable);
 
                        if (type == typeof (string [])) {
@@ -2016,10 +1906,34 @@ namespace System.Web.Compilation
                                }
                        }
 
-                       TypeConverter converter = preConverted ? cvt :
-                               wasNullable ? TypeDescriptor.GetConverter (type) :
-                               TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
+                       TypeConverter converter = preConverted ? cvt : wasNullable ? TypeDescriptor.GetConverter (type) : null;
+                       if (converter == null) {
+                               PropertyDescriptor pdesc = TypeDescriptor.GetProperties (member.DeclaringType) [member.Name];
+                               if (pdesc != null)
+                                       converter = pdesc.Converter;
+                               else {
+                                       Type memberType;
+                                       switch (member.MemberType) {
+                                               case MemberTypes.Field:
+                                                       memberType = ((FieldInfo)member).FieldType;
+                                                       break;
+
+                                               case MemberTypes.Property:
+                                                       memberType = ((PropertyInfo)member).PropertyType;
+                                                       break;
+
+                                               default:
+                                                       memberType = null;
+                                                       break;
+                                       }
+
+                                       if (memberType == null)
+                                               return null;
 
+                                       converter = TypeDescriptor.GetConverter (memberType);
+                               }
+                       }
+                       
                        if (preConverted || (converter != null && SafeCanConvertFrom (typeof (string), converter))) {
                                object value = preConverted ? convertedFromAttr : converter.ConvertFromInvariantString (str);
 
@@ -2029,7 +1943,11 @@ namespace System.Web.Compilation
                                                return CreateNullableExpression (originalType, GenerateInstance (idesc, true),
                                                                                 wasNullable);
 
-                                       return new CodeCastExpression (type, GenerateInstance (idesc, true));
+                                       CodeExpression instance = GenerateInstance (idesc, true);
+                                       if (type.IsPublic)
+                                               return new CodeCastExpression (type, instance);
+                                       else
+                                               return instance;
                                }
 
                                CodeExpression exp = GenerateObjectInstance (value, false);
@@ -2132,6 +2050,10 @@ namespace System.Web.Compilation
                {
                        if (value is System.Web.UI.WebControls.Unit) {
                                System.Web.UI.WebControls.Unit s = (System.Web.UI.WebControls.Unit) value;
+                               if (s.IsEmpty) {
+                                       FieldInfo f = typeof (Unit).GetField ("Empty");
+                                       return new InstanceDescriptor (f, null);
+                               }
                                ConstructorInfo c = typeof(System.Web.UI.WebControls.Unit).GetConstructor (
                                        BindingFlags.Instance | BindingFlags.Public,
                                        null,
@@ -2143,6 +2065,10 @@ namespace System.Web.Compilation
                        
                        if (value is System.Web.UI.WebControls.FontUnit) {
                                System.Web.UI.WebControls.FontUnit s = (System.Web.UI.WebControls.FontUnit) value;
+                               if (s.IsEmpty) {
+                                       FieldInfo f = typeof (FontUnit).GetField ("Empty");
+                                       return new InstanceDescriptor (f, null);
+                               }
 
                                Type cParamType = null;
                                object cParam = null;