-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I had a little bug open on the codefile stuff not working properly. The SVN patch didn't quite handle all the conditions, so I reopened the ticket at:
http://bugzilla.ximian.com/show_bug.cgi?id=76423 I also went through and created a patch for the code that should handle all the cases that I found from my research on the web. It is a little more involved, mainly because of ASP 2's use of partial classes and the need to use variables from the ending classes. I wrote it off today's SVN, so things should be fairly up-to-date. Also, to test it, I created a small web application that has the three forms of codefile/inherits and posted it in a zip file on the bug. Feedback, suggestions, and gouged out eyeballs from reading the horror of my code all appreciated. :) Cheers! -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFDdOzZLwDfJiZIuKARAmlqAJ9wtLJuFbJUlZfnj+wU6teXKGjxbACfftx2 CZILDeXmqA8MdFbQhno6sf0= =13NX -----END PGP SIGNATURE-----
Index: System.Web.UI/ControlBuilder.cs =================================================================== --- System.Web.UI/ControlBuilder.cs (revision 52911) +++ System.Web.UI/ControlBuilder.cs (working copy) @@ -497,6 +497,19 @@ { return CreateInstance (); } + + internal void ResetState() + { + haveParserVariable = false; + + if (Children != null) { + foreach (object child in Children) { + ControlBuilder cb = child as ControlBuilder; + if (cb != null) + cb.ResetState (); + } + } + } #endif } } Index: System.Web.UI/TemplateParser.cs =================================================================== --- System.Web.UI/TemplateParser.cs (revision 52911) +++ System.Web.UI/TemplateParser.cs (working copy) @@ -67,6 +67,10 @@ string oc_header, oc_custom, oc_param, oc_controls; bool oc_shared; OutputCacheLocation oc_location; +#if NET_2_0 + string src; + string partialClassName; +#endif Assembly srcAssembly; int appAssemblyIndex = -1; @@ -421,21 +425,48 @@ language = GetString (atts, "Language", CompilationConfig.DefaultLanguage); strictOn = GetBool (atts, "Strict", CompilationConfig.Strict); explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit); + + string inherits = GetString (atts, "Inherits", null); #if NET_2_0 - string src = GetString (atts, "CodeFile", null); + // In ASP 2, the source file is actually integrated with + // the generated file via the use of partial classes. This + // means that the code file has to be confirmed, but not + // used at this point. + src = GetString (atts, "CodeFile", null); + + if (src != null && inherits != null) { + // Make sure the source exists + src = UrlUtils.Combine (BaseVirtualDir, src); + string realPath = MapPath (src, false); + if (!File.Exists (realPath)) + ThrowParseException ("File " + src + " not found"); + + // Verify that the inherits is a valid identify not a + // fully-qualified name. + if (!CodeGenerator.IsValidLanguageIndependentIdentifier (inherits)) + ThrowParseException (String.Format ("'{0}' is not valid for 'inherits'", inherits)); + + // We are going to create a partial class that shares + // the same name as the inherits tag, so reset the + // name. The base type is changed because it is the + // code file's responsibilty to extend the classes + // needed. + partialClassName = inherits; + + // Add the code file as an option to the + // compiler. This lets both files be compiled at once. + compilerOptions += " " + realPath; + } else if (inherits != null) { + // We just set the inherits directly because this is a + // Single-Page model. + SetBaseType (inherits); + } #else string src = GetString (atts, "Src", null); -#endif + if (src != null) srcAssembly = GetAssemblyFromSource (src); - string inherits = GetString (atts, "Inherits", null); -#if NET_2_0 - if (srcAssembly == null) - className = inherits; - else - SetBaseType (inherits); -#else if (inherits != null) SetBaseType (inherits); @@ -498,6 +529,18 @@ set { inputFile = value; } } +#if NET_2_0 + internal bool IsPartial + { + get { return src != null; } + } + + internal string PartialClassName + { + get { return partialClassName; } + } +#endif + internal string Text { get { return text; } Index: System.Web.Compilation/CachingCompiler.cs =================================================================== --- System.Web.Compilation/CachingCompiler.cs (revision 52915) +++ System.Web.Compilation/CachingCompiler.cs (working copy) @@ -70,11 +70,18 @@ Cache cache = HttpRuntime.Cache; string key = cachePrefix + compiler.Parser.InputFile; CompilerResults results = (CompilerResults) cache [key]; + +#if NET_2_0 + if (!compiler.IsRebuildingPartial) +#endif if (results != null) return results; lock (compilationLock) { results = (CompilerResults) cache [key]; +#if NET_2_0 + if (!compiler.IsRebuildingPartial) +#endif if (results != null) return results; Index: System.Web.Compilation/BaseCompiler.cs =================================================================== --- System.Web.Compilation/BaseCompiler.cs (revision 52915) +++ System.Web.Compilation/BaseCompiler.cs (working copy) @@ -42,12 +42,21 @@ { abstract class BaseCompiler { +#if NET_2_0 + static BindingFlags replaceableFlags = BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance; +#endif + TemplateParser parser; CodeDomProvider provider; ICodeCompiler compiler; CodeCompileUnit unit; CodeNamespace mainNS; CompilerParameters compilerParameters; +#if NET_2_0 + bool isRebuilding = false; + protected Hashtable partialNameOverride = new Hashtable(); +#endif protected CodeTypeDeclaration mainClass; protected CodeTypeReferenceExpression mainClassExpr; protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression (); @@ -61,13 +70,25 @@ void Init () { unit = new CodeCompileUnit (); +#if NET_2_0 + if (parser.IsPartial) { + mainNS = new CodeNamespace (); + mainClass = new CodeTypeDeclaration (parser.PartialClassName); + mainClass.IsPartial = true; + mainClassExpr = new CodeTypeReferenceExpression (parser.PartialClassName); + } else { +#endif mainNS = new CodeNamespace ("ASP"); + mainClass = new CodeTypeDeclaration (parser.ClassName); + mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName)); + mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName); +#if NET_2_0 + } +#endif unit.Namespaces.Add (mainNS); - mainClass = new CodeTypeDeclaration (parser.ClassName); mainClass.TypeAttributes = TypeAttributes.Public; mainNS.Types.Add (mainClass); - mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName)); - mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName); + foreach (object o in parser.Imports) { if (o is string) mainNS.Imports.Add (new CodeNamespaceImport ((string) o)); @@ -111,6 +132,11 @@ ctor.Statements.AddRange (localVars); CodeTypeReferenceExpression r; +#if NET_2_0 + if (parser.IsPartial) + r = new CodeTypeReferenceExpression (mainClass.Name); + else +#endif r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name); CodeFieldReferenceExpression intialized; intialized = new CodeFieldReferenceExpression (r, "__intialized"); @@ -337,9 +363,90 @@ } results.TempFiles.Delete (); - return assembly.GetType (mainClassExpr.Type.BaseType, true); + Type mainClassType = assembly.GetType (mainClassExpr.Type.BaseType, true); + +#if NET_2_0 + if (parser.IsPartial) { + // With the partial classes, we need to make sure we + // don't have any methods that should have not been + // created (because they are accessible from the base + // types). We cannot do this normally because the + // codebehind file is actually a partial class and we + // have no way of identifying the partial class' base + // type until now. + if (!isRebuilding && CheckPartialBaseType (mainClassType)) { + isRebuilding = true; + parser.RootBuilder.ResetState (); + return GetCompiledType (); + } + } +#endif + + return mainClassType; } +#if NET_2_0 + internal bool IsRebuildingPartial + { + get { return isRebuilding; } + } + + internal bool CheckPartialBaseType (Type type) + { + // Get the base type. If we don't have any (bad thing), we + // don't need to replace ourselves. Also check for the + // core file, since that won't have any either. + Type baseType = type.BaseType; + if (baseType == null || baseType == typeof(System.Web.UI.Page)) + return false; + + bool rebuild = false; + + if (CheckPartialBaseFields (type, baseType)) + rebuild = true; + + if (CheckPartialBaseProperties (type, baseType)) + rebuild = true; + + return rebuild; + } + + internal bool CheckPartialBaseFields (Type type, Type baseType) + { + bool rebuild = false; + + foreach (FieldInfo baseInfo in baseType.GetFields (replaceableFlags)) { + if (baseInfo.IsPrivate) + continue; + + FieldInfo typeInfo = type.GetField (baseInfo.Name, replaceableFlags); + + if (typeInfo != null && typeInfo.DeclaringType == type) { + partialNameOverride [typeInfo.Name] = true; + rebuild = true; + } + } + + return rebuild; + } + + internal bool CheckPartialBaseProperties (Type type, Type baseType) + { + bool rebuild = false; + + foreach (PropertyInfo baseInfo in baseType.GetProperties ()) { + PropertyInfo typeInfo = type.GetProperty (baseInfo.Name); + + if (typeInfo != null && typeInfo.DeclaringType == type) { + partialNameOverride [typeInfo.Name] = true; + rebuild = true; + } + } + + return rebuild; + } +#endif + internal CompilerParameters CompilerParameters { get { return compilerParameters; } } Index: System.Web.Compilation/TemplateControlCompiler.cs =================================================================== --- System.Web.Compilation/TemplateControlCompiler.cs (revision 52915) +++ System.Web.Compilation/TemplateControlCompiler.cs (working copy) @@ -77,6 +77,10 @@ void CreateField (ControlBuilder builder, bool check) { +#if NET_2_0 + if (partialNameOverride [builder.ID] != null) + return; +#endif currentLocation = builder.location; if (check && CheckBaseFieldOrProperty (builder.ID, builder.ControlType)) return; // The field or property already exists in a base class and is accesible.
_______________________________________________ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list