2010-03-02 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Web / System.Web.Compilation / BaseCompiler.cs
blob393f34979b47f43ebe79d7ccbd9d1e2126428b63
1 //
2 // System.Web.Compilation.BaseCompiler
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (c) Copyright 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System;
32 using System.CodeDom;
33 using System.CodeDom.Compiler;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
37 using System.Text;
38 using System.Web.UI;
39 using System.Web.Configuration;
40 using System.IO;
42 namespace System.Web.Compilation
44 abstract class BaseCompiler
46 const string DEFAULT_NAMESPACE = "ASP";
47 internal static Guid HashMD5 = new Guid(0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99);
48 static BindingFlags replaceableFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
50 TemplateParser parser;
51 CodeDomProvider provider;
52 ICodeCompiler compiler;
53 CodeCompileUnit unit;
54 CodeNamespace mainNS;
55 CompilerParameters compilerParameters;
56 bool isRebuilding = false;
57 protected Hashtable partialNameOverride = new Hashtable();
58 protected CodeTypeDeclaration partialClass;
59 protected CodeTypeReferenceExpression partialClassExpr;
60 protected CodeTypeDeclaration mainClass;
61 protected CodeTypeReferenceExpression mainClassExpr;
62 protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
64 VirtualPath inputVirtualPath;
66 public VirtualPath InputVirtualPath {
67 get {
68 if (inputVirtualPath == null)
69 inputVirtualPath = new VirtualPath (VirtualPathUtility.Combine (parser.BaseVirtualDir, Path.GetFileName (parser.InputFile)));
71 return inputVirtualPath;
75 protected BaseCompiler (TemplateParser parser)
77 this.parser = parser;
80 protected void AddReferencedAssembly (Assembly asm)
82 if (unit == null || asm == null)
83 return;
85 StringCollection refAsm = unit.ReferencedAssemblies;
86 string asmLocation = asm.Location;
87 if (!refAsm.Contains (asmLocation))
88 refAsm.Add (asmLocation);
91 internal CodeStatement AddLinePragma (CodeExpression expression, ControlBuilder builder)
93 return AddLinePragma (new CodeExpressionStatement (expression), builder);
96 internal CodeStatement AddLinePragma (CodeStatement statement, ControlBuilder builder)
98 if (builder == null || statement == null)
99 return statement;
101 ILocation location = null;
103 if (!(builder is CodeRenderBuilder))
104 location = builder.Location;
106 if (location != null)
107 return AddLinePragma (statement, location);
108 else
109 return AddLinePragma (statement, builder.Line, builder.FileName);
112 internal CodeStatement AddLinePragma (CodeStatement statement, ILocation location)
114 if (location == null || statement == null)
115 return statement;
117 return AddLinePragma (statement, location.BeginLine, location.Filename);
120 bool IgnoreFile (string fileName)
122 if (parser != null && !parser.LinePragmasOn)
123 return true;
125 return String.Compare (fileName, "@@inner_string@@", StringComparison.OrdinalIgnoreCase) == 0;
128 internal CodeStatement AddLinePragma (CodeStatement statement, int line, string fileName)
130 if (statement == null || IgnoreFile (fileName))
131 return statement;
133 statement.LinePragma = new CodeLinePragma (fileName, line);
134 return statement;
137 internal CodeTypeMember AddLinePragma (CodeTypeMember member, ControlBuilder builder)
139 if (builder == null || member == null)
140 return member;
142 ILocation location = builder.Location;
144 if (location != null)
145 return AddLinePragma (member, location);
146 else
147 return AddLinePragma (member, builder.Line, builder.FileName);
150 internal CodeTypeMember AddLinePragma (CodeTypeMember member, ILocation location)
152 if (location == null || member == null)
153 return member;
155 return AddLinePragma (member, location.BeginLine, location.Filename);
158 internal CodeTypeMember AddLinePragma (CodeTypeMember member, int line, string fileName)
160 if (member == null || IgnoreFile (fileName))
161 return member;
163 member.LinePragma = new CodeLinePragma (fileName, line);
164 return member;
167 internal void ConstructType ()
169 unit = new CodeCompileUnit ();
170 byte[] md5checksum = parser.MD5Checksum;
172 if (md5checksum != null) {
173 CodeChecksumPragma pragma = new CodeChecksumPragma ();
174 pragma.FileName = parser.InputFile;
175 pragma.ChecksumAlgorithmId = HashMD5;
176 pragma.ChecksumData = md5checksum;
178 unit.StartDirectives.Add (pragma);
181 if (parser.IsPartial) {
182 string partialns = null;
183 string partialclasstype = parser.PartialClassName;
185 int partialdot = partialclasstype.LastIndexOf ('.');
186 if (partialdot != -1) {
187 partialns = partialclasstype.Substring (0, partialdot);
188 partialclasstype = partialclasstype.Substring (partialdot + 1);
191 CodeNamespace partialNS = new CodeNamespace (partialns);
192 partialClass = new CodeTypeDeclaration (partialclasstype);
193 partialClass.IsPartial = true;
194 partialClassExpr = new CodeTypeReferenceExpression (parser.PartialClassName);
196 unit.Namespaces.Add (partialNS);
197 partialClass.TypeAttributes = TypeAttributes.Public;
198 partialNS.Types.Add (partialClass);
201 string mainclasstype = parser.ClassName;
202 string mainns = DEFAULT_NAMESPACE;
203 int maindot = mainclasstype.LastIndexOf ('.');
204 if (maindot != -1) {
205 mainns = mainclasstype.Substring (0, maindot);
206 mainclasstype = mainclasstype.Substring (maindot + 1);
209 mainNS = new CodeNamespace (mainns);
210 mainClass = new CodeTypeDeclaration (mainclasstype);
211 CodeTypeReference baseTypeRef;
212 if (partialClass != null) {
213 baseTypeRef = new CodeTypeReference (parser.PartialClassName);
214 baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
215 } else {
216 baseTypeRef = new CodeTypeReference (parser.BaseType.FullName);
217 if (parser.BaseTypeIsGlobal)
218 baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
220 mainClass.BaseTypes.Add (baseTypeRef);
222 mainClassExpr = new CodeTypeReferenceExpression (mainns + "." + mainclasstype);
224 unit.Namespaces.Add (mainNS);
225 mainClass.TypeAttributes = TypeAttributes.Public;
226 mainNS.Types.Add (mainClass);
228 foreach (object o in parser.Imports.Keys) {
229 if (o is string)
230 mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
233 // StringCollection.Contains has O(n) complexity, but
234 // considering the number of comparisons we make on
235 // average and the fact that using an intermediate array
236 // would be even more costly, this is fine here.
237 StringCollection refAsm = unit.ReferencedAssemblies;
238 string asmName;
239 if (parser.Assemblies != null) {
240 foreach (object o in parser.Assemblies) {
241 asmName = o as string;
242 if (asmName != null && !refAsm.Contains (asmName))
243 refAsm.Add (asmName);
247 ArrayList al = WebConfigurationManager.ExtraAssemblies;
248 if (al != null && al.Count > 0) {
249 foreach (object o in al) {
250 asmName = o as string;
251 if (asmName != null && !refAsm.Contains (asmName))
252 refAsm.Add (asmName);
256 IList list = BuildManager.CodeAssemblies;
257 if (list != null && list.Count > 0) {
258 Assembly asm;
259 foreach (object o in list) {
260 asm = o as Assembly;
261 if (o == null)
262 continue;
263 asmName = asm.Location;
264 if (asmName != null && !refAsm.Contains (asmName))
265 refAsm.Add (asmName);
269 // Late-bound generators specifics (as for MonoBASIC/VB.NET)
270 unit.UserData["RequireVariableDeclaration"] = parser.ExplicitOn;
271 unit.UserData["AllowLateBound"] = !parser.StrictOn;
273 InitializeType ();
274 AddInterfaces ();
275 AddClassAttributes ();
276 CreateStaticFields ();
277 AddApplicationAndSessionObjects ();
278 AddScripts ();
279 CreateMethods ();
280 CreateConstructor (null, null);
283 internal CodeFieldReferenceExpression GetMainClassFieldReferenceExpression (string fieldName)
285 CodeTypeReference mainClassTypeRef;
286 mainClassTypeRef = new CodeTypeReference (mainNS.Name + "." + mainClass.Name);
287 mainClassTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
289 return new CodeFieldReferenceExpression (
290 new CodeTypeReferenceExpression (mainClassTypeRef), fieldName);
293 protected virtual void InitializeType ()
296 protected virtual void CreateStaticFields ()
298 CodeMemberField fld = new CodeMemberField (typeof (bool), "__initialized");
299 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
300 fld.InitExpression = new CodePrimitiveExpression (false);
301 mainClass.Members.Add (fld);
304 void AssignAppRelativeVirtualPath (CodeConstructor ctor)
306 if (String.IsNullOrEmpty (parser.InputFile))
307 return;
309 Type baseType = parser.CodeFileBaseClassType;
310 if (baseType == null)
311 baseType = parser.BaseType;
312 if (baseType == null)
313 return;
314 if (!baseType.IsSubclassOf (typeof (System.Web.UI.TemplateControl)))
315 return;
317 CodeTypeReference baseTypeRef = new CodeTypeReference (baseType.FullName);
318 if (parser.BaseTypeIsGlobal)
319 baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
321 CodeExpression cast = new CodeCastExpression (baseTypeRef, new CodeThisReferenceExpression ());
322 CodePropertyReferenceExpression arvpProp = new CodePropertyReferenceExpression (cast, "AppRelativeVirtualPath");
323 CodeAssignStatement arvpAssign = new CodeAssignStatement ();
324 arvpAssign.Left = arvpProp;
325 arvpAssign.Right = new CodePrimitiveExpression (VirtualPathUtility.RemoveTrailingSlash (InputVirtualPath.AppRelative));
326 ctor.Statements.Add (arvpAssign);
329 protected virtual void CreateConstructor (CodeStatementCollection localVars,
330 CodeStatementCollection trueStmt)
332 CodeConstructor ctor = new CodeConstructor ();
333 ctor.Attributes = MemberAttributes.Public;
334 mainClass.Members.Add (ctor);
336 if (localVars != null)
337 ctor.Statements.AddRange (localVars);
339 AssignAppRelativeVirtualPath (ctor);
341 CodeFieldReferenceExpression initialized = GetMainClassFieldReferenceExpression ("__initialized");
343 CodeBinaryOperatorExpression bin;
344 bin = new CodeBinaryOperatorExpression (initialized,
345 CodeBinaryOperatorType.ValueEquality,
346 new CodePrimitiveExpression (false));
348 CodeAssignStatement assign = new CodeAssignStatement (initialized,
349 new CodePrimitiveExpression (true));
351 CodeConditionStatement cond = new CodeConditionStatement ();
352 cond.Condition = bin;
354 if (trueStmt != null)
355 cond.TrueStatements.AddRange (trueStmt);
356 cond.TrueStatements.Add (assign);
357 ctor.Statements.Add (cond);
358 AddStatementsToConstructor (ctor);
361 protected virtual void AddStatementsToConstructor (CodeConstructor ctor)
365 void AddScripts ()
367 if (parser.Scripts == null || parser.Scripts.Count == 0)
368 return;
370 ServerSideScript sss;
372 foreach (object o in parser.Scripts) {
373 sss = o as ServerSideScript;
375 if (sss == null)
376 continue;
378 mainClass.Members.Add (AddLinePragma (new CodeSnippetTypeMember (sss.Script), sss.Location));
382 protected internal virtual void CreateMethods ()
386 void InternalCreatePageProperty (string retType, string name, string contextProperty)
388 CodeMemberProperty property = new CodeMemberProperty ();
389 property.Name = name;
390 property.Type = new CodeTypeReference (retType);
391 property.Attributes = MemberAttributes.Family | MemberAttributes.Final;
393 CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
394 CodeCastExpression cast = new CodeCastExpression ();
395 ret.Expression = cast;
397 CodePropertyReferenceExpression refexp = new CodePropertyReferenceExpression ();
398 refexp.TargetObject = new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), "Context");
399 refexp.PropertyName = contextProperty;
401 cast.TargetType = new CodeTypeReference (retType);
402 cast.Expression = refexp;
404 property.GetStatements.Add (ret);
405 if (partialClass == null)
406 mainClass.Members.Add (property);
407 else
408 partialClass.Members.Add (property);
411 protected void CreateProfileProperty ()
413 string retType;
414 if (AppCodeCompiler.HaveCustomProfile (WebConfigurationManager.GetWebApplicationSection ("system.web/profile") as ProfileSection))
415 retType = "ProfileCommon";
416 else
417 retType = "System.Web.Profile.DefaultProfile";
418 InternalCreatePageProperty (retType, "Profile", "Profile");
421 protected virtual void AddInterfaces ()
423 if (parser.Interfaces == null)
424 return;
426 foreach (object o in parser.Interfaces) {
427 if (o is string)
428 mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
432 protected virtual void AddClassAttributes ()
436 protected virtual void AddApplicationAndSessionObjects ()
440 /* Utility methods for <object> stuff */
441 protected void CreateApplicationOrSessionPropertyForObject (Type type,
442 string propName,
443 bool isApplication,
444 bool isPublic)
446 /* if isApplication this generates (the 'cachedapp' field is created earlier):
447 private MyNS.MyClass app {
448 get {
449 if ((this.cachedapp == null)) {
450 this.cachedapp = ((MyNS.MyClass)
451 (this.Application.StaticObjects.GetObject("app")));
453 return this.cachedapp;
457 else, this is for Session:
458 private MyNS.MyClass ses {
459 get {
460 return ((MyNS.MyClass) (this.Session.StaticObjects.GetObject("ses")));
466 CodeExpression result = null;
468 CodeMemberProperty prop = new CodeMemberProperty ();
469 prop.Type = new CodeTypeReference (type);
470 prop.Name = propName;
471 if (isPublic)
472 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
473 else
474 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
476 CodePropertyReferenceExpression p1;
477 if (isApplication)
478 p1 = new CodePropertyReferenceExpression (thisRef, "Application");
479 else
480 p1 = new CodePropertyReferenceExpression (thisRef, "Session");
482 CodePropertyReferenceExpression p2;
483 p2 = new CodePropertyReferenceExpression (p1, "StaticObjects");
485 CodeMethodReferenceExpression getobject;
486 getobject = new CodeMethodReferenceExpression (p2, "GetObject");
488 CodeMethodInvokeExpression invoker;
489 invoker = new CodeMethodInvokeExpression (getobject,
490 new CodePrimitiveExpression (propName));
492 CodeCastExpression cast = new CodeCastExpression (prop.Type, invoker);
494 if (isApplication) {
495 CodeFieldReferenceExpression field;
496 field = new CodeFieldReferenceExpression (thisRef, "cached" + propName);
498 CodeConditionStatement stmt = new CodeConditionStatement();
499 stmt.Condition = new CodeBinaryOperatorExpression (field,
500 CodeBinaryOperatorType.IdentityEquality,
501 new CodePrimitiveExpression (null));
503 CodeAssignStatement assign = new CodeAssignStatement ();
504 assign.Left = field;
505 assign.Right = cast;
506 stmt.TrueStatements.Add (assign);
507 prop.GetStatements.Add (stmt);
508 result = field;
509 } else {
510 result = cast;
513 prop.GetStatements.Add (new CodeMethodReturnStatement (result));
514 mainClass.Members.Add (prop);
517 protected string CreateFieldForObject (Type type, string name)
519 string fieldName = "cached" + name;
520 CodeMemberField f = new CodeMemberField (type, fieldName);
521 f.Attributes = MemberAttributes.Private;
522 mainClass.Members.Add (f);
523 return fieldName;
526 protected void CreatePropertyForObject (Type type, string propName, string fieldName, bool isPublic)
528 CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
529 CodeMemberProperty prop = new CodeMemberProperty ();
530 prop.Type = new CodeTypeReference (type);
531 prop.Name = propName;
532 if (isPublic)
533 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
534 else
535 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
537 CodeConditionStatement stmt = new CodeConditionStatement();
538 stmt.Condition = new CodeBinaryOperatorExpression (field,
539 CodeBinaryOperatorType.IdentityEquality,
540 new CodePrimitiveExpression (null));
542 CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type);
543 stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
544 prop.GetStatements.Add (stmt);
545 prop.GetStatements.Add (new CodeMethodReturnStatement (field));
547 mainClass.Members.Add (prop);
549 /******/
551 void CheckCompilerErrors (CompilerResults results)
553 if (results.NativeCompilerReturnValue == 0)
554 return;
556 string fileText = null;
557 CompilerErrorCollection errors = results.Errors;
558 CompilerError ce = (errors != null && errors.Count > 0) ? errors [0] : null;
559 string inFile = (ce != null) ? ce.FileName : null;
561 if (inFile != null && File.Exists (inFile)) {
562 using (StreamReader sr = File.OpenText (inFile)) {
563 fileText = sr.ReadToEnd ();
565 } else {
566 StringWriter writer = new StringWriter();
567 provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
568 fileText = writer.ToString ();
570 throw new CompilationException (parser.InputFile, errors, fileText);
573 protected string DynamicDir ()
575 return AppDomain.CurrentDomain.SetupInformation.DynamicBase;
578 internal static CodeDomProvider CreateProvider (string lang)
580 CompilerParameters par;
581 string tempdir;
583 return CreateProvider (HttpContext.Current, lang, out par, out tempdir);
586 internal static CodeDomProvider CreateProvider (string lang, out string compilerOptions, out int warningLevel, out string tempdir)
588 return CreateProvider (HttpContext.Current, lang, out compilerOptions, out warningLevel, out tempdir);
591 internal static CodeDomProvider CreateProvider (HttpContext context, string lang, out string compilerOptions, out int warningLevel, out string tempdir)
593 CodeDomProvider ret;
594 CompilerParameters par;
596 ret = CreateProvider (context, lang, out par, out tempdir);
597 if (par != null){
598 warningLevel = par.WarningLevel;
599 compilerOptions = par.CompilerOptions;
600 } else {
601 warningLevel = 2;
602 compilerOptions = String.Empty;
605 return ret;
608 internal static CodeDomProvider CreateProvider (HttpContext context, string lang, out CompilerParameters par, out string tempdir)
610 CodeDomProvider ret = null;
611 par = null;
613 CompilationSection config = (CompilationSection) WebConfigurationManager.GetWebApplicationSection ("system.web/compilation");
614 Compiler comp = config.Compilers[lang];
616 if (comp == null) {
617 CompilerInfo info = CodeDomProvider.GetCompilerInfo (lang);
618 if (info != null && info.IsCodeDomProviderTypeValid) {
619 ret = info.CreateProvider ();
620 par = info.CreateDefaultCompilerParameters ();
622 } else {
623 Type t = HttpApplication.LoadType (comp.Type, true);
624 ret = Activator.CreateInstance (t) as CodeDomProvider;
626 par = new CompilerParameters ();
627 par.CompilerOptions = comp.CompilerOptions;
628 par.WarningLevel = comp.WarningLevel;
630 tempdir = config.TempDirectory;
632 return ret;
635 [MonoTODO ("find out how to extract the warningLevel and compilerOptions in the <system.codedom> case")]
636 public virtual Type GetCompiledType ()
638 Type type = CachingCompiler.GetTypeFromCache (parser.InputFile);
639 if (type != null)
640 return type;
642 ConstructType ();
643 string lang = parser.Language;
644 string tempdir;
645 string compilerOptions;
646 int warningLevel;
648 Provider = CreateProvider (parser.Context, lang, out compilerOptions, out warningLevel, out tempdir);
649 if (Provider == null)
650 throw new HttpException ("Configuration error. Language not supported: " +
651 lang, 500);
653 CompilerParameters parameters = CompilerParameters;
654 parameters.IncludeDebugInformation = parser.Debug;
655 parameters.CompilerOptions = compilerOptions + " " + parser.CompilerOptions;
656 parameters.WarningLevel = warningLevel;
658 bool keepFiles = (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") != null);
660 if (tempdir == null || tempdir == "")
661 tempdir = DynamicDir ();
663 TempFileCollection tempcoll = new TempFileCollection (tempdir, keepFiles);
664 parameters.TempFiles = tempcoll;
665 string dllfilename = Path.GetFileName (tempcoll.AddExtension ("dll", true));
666 parameters.OutputAssembly = Path.Combine (DynamicDir (), dllfilename);
668 CompilerResults results = CachingCompiler.Compile (this);
669 CheckCompilerErrors (results);
670 Assembly assembly = results.CompiledAssembly;
671 if (assembly == null) {
672 if (!File.Exists (parameters.OutputAssembly)) {
673 results.TempFiles.Delete ();
674 throw new CompilationException (parser.InputFile, results.Errors,
675 "No assembly returned after compilation!?");
678 assembly = Assembly.LoadFrom (parameters.OutputAssembly);
681 results.TempFiles.Delete ();
682 Type mainClassType = assembly.GetType (MainClassType, true);
684 if (parser.IsPartial) {
685 // With the partial classes, we need to make sure we
686 // don't have any methods that should have not been
687 // created (because they are accessible from the base
688 // types). We cannot do this normally because the
689 // codebehind file is actually a partial class and we
690 // have no way of identifying the partial class' base
691 // type until now.
692 if (!isRebuilding && CheckPartialBaseType (mainClassType)) {
693 isRebuilding = true;
694 parser.RootBuilder.ResetState ();
695 return GetCompiledType ();
699 return mainClassType;
702 internal string MainClassType {
703 get {
704 if (mainClassExpr == null)
705 return null;
707 return mainClassExpr.Type.BaseType;
711 internal bool IsRebuildingPartial
713 get { return isRebuilding; }
716 internal bool CheckPartialBaseType (Type type)
718 // Get the base type. If we don't have any (bad thing), we
719 // don't need to replace ourselves. Also check for the
720 // core file, since that won't have any either.
721 Type baseType = type.BaseType;
722 if (baseType == null || baseType == typeof(System.Web.UI.Page))
723 return false;
725 bool rebuild = false;
727 if (CheckPartialBaseFields (type, baseType))
728 rebuild = true;
730 if (CheckPartialBaseProperties (type, baseType))
731 rebuild = true;
733 return rebuild;
736 internal bool CheckPartialBaseFields (Type type, Type baseType)
738 bool rebuild = false;
740 foreach (FieldInfo baseInfo in baseType.GetFields (replaceableFlags)) {
741 if (baseInfo.IsPrivate)
742 continue;
744 FieldInfo typeInfo = type.GetField (baseInfo.Name, replaceableFlags);
746 if (typeInfo != null && typeInfo.DeclaringType == type) {
747 partialNameOverride [typeInfo.Name] = true;
748 rebuild = true;
752 return rebuild;
755 internal bool CheckPartialBaseProperties (Type type, Type baseType)
757 bool rebuild = false;
759 foreach (PropertyInfo baseInfo in baseType.GetProperties ()) {
760 PropertyInfo typeInfo = type.GetProperty (baseInfo.Name);
762 if (typeInfo != null && typeInfo.DeclaringType == type) {
763 partialNameOverride [typeInfo.Name] = true;
764 rebuild = true;
768 return rebuild;
771 internal CodeDomProvider Provider {
772 get { return provider; }
773 set { provider = value; }
776 internal ICodeCompiler Compiler {
777 get { return compiler; }
778 set { compiler = value; }
781 internal CompilerParameters CompilerParameters {
782 get {
783 if (compilerParameters == null)
784 compilerParameters = new CompilerParameters ();
786 return compilerParameters;
789 set { compilerParameters = value; }
792 internal CodeCompileUnit CompileUnit {
793 get { return unit; }
796 internal CodeTypeDeclaration DerivedType {
797 get { return mainClass; }
800 internal CodeTypeDeclaration BaseType {
801 get {
802 if (partialClass == null)
803 return DerivedType;
804 return partialClass;
808 internal TemplateParser Parser {
809 get { return parser; }