2010-06-05 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / PageCompiler.cs
1 //
2 // System.Web.Compilation.PageCompiler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
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.
29 //
30 using System;
31 using System.CodeDom;
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.IO;
35 using System.Reflection;
36 using System.Text;
37 using System.Web.Configuration;
38 using System.Web.UI;
39 using System.Web.SessionState;
40 using System.Web.Util;
41 using System.Web.Profile;
42
43 namespace System.Web.Compilation
44 {
45         class PageCompiler : TemplateControlCompiler
46         {
47                 PageParser pageParser;
48                 static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
49
50                 public PageCompiler (PageParser pageParser)
51                         : base (pageParser)
52                 {
53                         this.pageParser = pageParser;
54                 }
55
56                 protected override void CreateStaticFields ()
57                 {
58                         base.CreateStaticFields ();
59                         
60                         CodeMemberField fld = new CodeMemberField (typeof (object), "__fileDependencies");
61                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
62                         fld.InitExpression = new CodePrimitiveExpression (null);
63                         mainClass.Members.Add (fld);
64
65                         if (pageParser.OutputCache) {
66                                 fld = new CodeMemberField (typeof (OutputCacheParameters), "__outputCacheSettings");
67                                 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
68                                 fld.InitExpression = new CodePrimitiveExpression (null);
69                                 mainClass.Members.Add (fld);
70                         }
71                 }
72                 
73                 protected override void CreateConstructor (CodeStatementCollection localVars,
74                                                            CodeStatementCollection trueStmt)
75                 {
76                         MainDirectiveAttribute <string> masterPageFile = pageParser.MasterPageFile;
77                         if (masterPageFile != null && !masterPageFile.IsExpression)
78                                 // This is here just to trigger master page build, so that its type
79                                 // is available when compiling the page itself.
80                                 BuildManager.GetCompiledType (masterPageFile.Value);
81
82                         MainDirectiveAttribute <string> clientTarget;
83                         clientTarget = pageParser.ClientTarget;
84                         if (clientTarget != null) {
85                                 CodeExpression prop;
86                                 prop = new CodePropertyReferenceExpression (thisRef, "ClientTarget");
87                                 CodeExpression ct = null;
88
89                                 if (clientTarget.IsExpression) {
90                                         var pi = GetFieldOrProperty (typeof (Page), "ClientTarget") as PropertyInfo;
91                                         if (pi != null)
92                                                 ct = CompileExpression (pi, pi.PropertyType, clientTarget.UnparsedValue, false);
93                                 }
94
95                                 if (ct == null)
96                                         ct = new CodePrimitiveExpression (clientTarget.Value);
97                                 if (localVars == null)
98                                         localVars = new CodeStatementCollection ();
99                                 localVars.Add (new CodeAssignStatement (prop, ct));
100                         }
101
102                         ArrayList deps = pageParser.Dependencies;
103                         int depsCount = deps != null ? deps.Count : 0;
104                         
105                         if (depsCount > 0) {
106                                 if (localVars == null)
107                                         localVars = new CodeStatementCollection ();
108                                 if (trueStmt == null)
109                                         trueStmt = new CodeStatementCollection ();
110
111                                 CodeAssignStatement assign;
112                                 localVars.Add (
113                                         new CodeVariableDeclarationStatement (
114                                                 typeof (string[]),
115                                                 "dependencies")
116                                 );
117
118                                 CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
119                                 trueStmt.Add (
120                                         new CodeAssignStatement (dependencies, new CodeArrayCreateExpression (typeof (string), depsCount))
121                                 );
122                                 
123                                 CodeArrayIndexerExpression arrayIndex;
124                                 object o;
125                                 
126                                 for (int i = 0; i < depsCount; i++) {
127                                         o = deps [i];
128                                         arrayIndex = new CodeArrayIndexerExpression (dependencies, new CodeExpression[] {new CodePrimitiveExpression (i)});
129                                         assign = new CodeAssignStatement (arrayIndex, new CodePrimitiveExpression (o));
130                                         trueStmt.Add (assign);
131                                 }
132                                 
133                                 CodeMethodInvokeExpression getDepsCall = new CodeMethodInvokeExpression (
134                                         thisRef,
135                                         "GetWrappedFileDependencies",
136                                         new CodeExpression[] {dependencies}
137                                 );
138                                 assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), getDepsCall);
139
140                                 trueStmt.Add (assign);
141                         }
142
143                         base.CreateConstructor (localVars, trueStmt);
144                 }
145                 
146                 protected override void AddInterfaces () 
147                 {
148                         base.AddInterfaces ();
149                         CodeTypeReference cref;
150                         
151                         if (pageParser.EnableSessionState) {
152                                 cref = new CodeTypeReference (typeof (IRequiresSessionState));
153                                 if (partialClass != null)
154                                         partialClass.BaseTypes.Add (cref);
155                                 else
156                                         mainClass.BaseTypes.Add (cref);
157                         }
158                         
159                         if (pageParser.ReadOnlySessionState) {
160                                 cref = new CodeTypeReference (typeof (IReadOnlySessionState));
161                                 if (partialClass != null)
162                                         partialClass.BaseTypes.Add (cref);                                      
163                                 else
164                                         mainClass.BaseTypes.Add (cref);
165                         }
166
167                         if (pageParser.Async)
168                                 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpAsyncHandler)));
169                         
170                         mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpHandler)));
171                 }
172
173                 void CreateGetTypeHashCode () 
174                 {
175                         CodeMemberMethod method = new CodeMemberMethod ();
176                         method.ReturnType = intRef;
177                         method.Name = "GetTypeHashCode";
178                         method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
179                         Random rnd = new Random (pageParser.InputFile.GetHashCode ());
180                         method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
181                         mainClass.Members.Add (method);
182                 }
183
184                 static CodeExpression GetExpressionForValueAndType (object value, Type valueType)
185                 {
186                         // Put short circuit types here
187                         if (valueType == typeof (TimeSpan)) {
188                                 CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression (
189                                         new CodeTypeReferenceExpression (typeof (TimeSpan)),
190                                         "Parse");
191
192                                 return new CodeMethodInvokeExpression (
193                                         mref,
194                                         new CodeExpression[] { new CodePrimitiveExpression (((TimeSpan) value).ToString ()) }
195                                 );
196                         }
197
198                         throw new HttpException (String.Format ("Unable to create assign expression for type '{0}'.", valueType));
199                 }
200
201                 static CodeAssignStatement CreatePropertyAssign (CodeExpression owner, string name, CodeExpression rhs)
202                 {
203                         return new CodeAssignStatement (new CodePropertyReferenceExpression (owner, name), rhs);
204                 }
205                 
206                 static CodeAssignStatement CreatePropertyAssign (CodeExpression owner, string name, object value)
207                 {
208                         CodeExpression rhs;
209                         if (value == null || value is string)
210                                 rhs = new CodePrimitiveExpression (value);
211                         else {
212                                 Type vt = value.GetType ();
213
214                                 if (vt.IsPrimitive)
215                                         rhs = new CodePrimitiveExpression (value);
216                                 else
217                                         rhs = GetExpressionForValueAndType (value, vt);
218                         }
219                         
220                         return CreatePropertyAssign (owner, name, rhs);
221                 }
222
223                 static CodeAssignStatement CreatePropertyAssign (string name, object value)
224                 {
225                         return CreatePropertyAssign (thisRef, name, value);
226                 }
227
228                 void AssignPropertyWithExpression <T> (CodeMemberMethod method, string name, MainDirectiveAttribute <T> value, ILocation location)
229                 {
230                         if (value == null)
231                                 return;
232                         CodeAssignStatement assign;
233                         CodeExpression rhs = null;
234                         
235                         if (value.IsExpression) {
236                                 var pi = GetFieldOrProperty (typeof (Page), name) as PropertyInfo;
237                                 if (pi != null)
238                                         rhs = CompileExpression (pi, pi.PropertyType, value.UnparsedValue, false);
239                         }
240                         
241                         if (rhs != null)
242                                 assign = CreatePropertyAssign (thisRef, name, rhs);
243                         else
244                                 assign = CreatePropertyAssign (name, value.Value);
245
246                         method.Statements.Add (AddLinePragma (assign, location));
247                 }
248                 
249                 void AddStatementsFromDirective (ControlBuilder builder, CodeMemberMethod method, ILocation location)
250                 {
251                         AssignPropertyWithExpression <string> (method, "ResponseEncoding", pageParser.ResponseEncoding, location);
252                         AssignPropertyWithExpression <int> (method, "CodePage", pageParser.CodePage, location);
253                         AssignPropertyWithExpression <int> (method, "LCID", pageParser.LCID, location);
254
255                         string contentType = pageParser.ContentType;
256                         if (contentType != null)
257                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign ("ContentType", contentType), location));
258
259                         string culture = pageParser.Culture;
260                         if (culture != null)
261                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign ("Culture", culture), location));
262
263                         culture = pageParser.UICulture;
264                         if (culture != null)
265                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign ("UICulture", culture), location));
266
267                         string errorPage = pageParser.ErrorPage;
268                         if (errorPage != null)
269                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign ("ErrorPage", errorPage), location));
270
271                         if (pageParser.HaveTrace) {
272                                 CodeAssignStatement stmt = new CodeAssignStatement ();
273                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceEnabled");
274                                 stmt.Right = new CodePrimitiveExpression (pageParser.Trace);
275                                 method.Statements.Add (AddLinePragma (stmt, location));
276                         }
277
278                         if (pageParser.TraceMode != TraceMode.Default) {
279                                 CodeAssignStatement stmt = new CodeAssignStatement ();
280                                 CodeTypeReferenceExpression tm = new CodeTypeReferenceExpression ("System.Web.TraceMode");
281                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceModeValue");
282                                 stmt.Right = new CodeFieldReferenceExpression (tm, pageParser.TraceMode.ToString ());
283                                 method.Statements.Add (AddLinePragma (stmt, location));
284                         }
285
286                         if (pageParser.NotBuffer) {
287                                 CodeAssignStatement stmt = new CodeAssignStatement ();
288                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "Buffer");
289                                 stmt.Right = new CodePrimitiveExpression (false);
290                                 method.Statements.Add (AddLinePragma (stmt, location));
291                         }
292
293                         if (!pageParser.EnableEventValidation) {
294                                 CodeAssignStatement stmt = new CodeAssignStatement ();
295                                 CodePropertyReferenceExpression prop;
296                                 prop = new CodePropertyReferenceExpression (thisRef, "EnableEventValidation");
297                                 stmt.Left = prop;
298                                 stmt.Right = new CodePrimitiveExpression (pageParser.EnableEventValidation);
299                                 method.Statements.Add (AddLinePragma (stmt, location));
300                         }
301
302                         if (pageParser.MaintainScrollPositionOnPostBack) {
303                                 CodeAssignStatement stmt = new CodeAssignStatement ();
304                                 CodePropertyReferenceExpression prop;
305                                 prop = new CodePropertyReferenceExpression (thisRef, "MaintainScrollPositionOnPostBack");
306                                 stmt.Left = prop;
307                                 stmt.Right = new CodePrimitiveExpression (pageParser.MaintainScrollPositionOnPostBack);
308                                 method.Statements.Add (AddLinePragma (stmt, location));
309                         }
310                 }
311
312                 protected override void AddStatementsToConstructor (CodeConstructor ctor)
313                 {
314                         base.AddStatementsToConstructor (ctor);
315                         if (pageParser.OutputCache)
316                                 OutputCacheParamsBlock (ctor);
317                 }
318                 
319                 protected override void AddStatementsToInitMethodTop (ControlBuilder builder, CodeMemberMethod method)
320                 {
321                         ILocation directiveLocation = pageParser.DirectiveLocation;
322                         AddStatementsFromDirective (builder, method, directiveLocation);
323
324                         CodeArgumentReferenceExpression ctrlVar = new CodeArgumentReferenceExpression("__ctrl");
325                         if (pageParser.EnableViewStateMacSet)
326                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "EnableViewStateMac", pageParser.EnableViewStateMacSet), directiveLocation));
327
328                         AssignPropertyWithExpression <string> (method, "Title", pageParser.Title, directiveLocation);
329                         AssignPropertyWithExpression <string> (method, "MasterPageFile", pageParser.MasterPageFile, directiveLocation);
330                         AssignPropertyWithExpression <string> (method, "Theme", pageParser.Theme, directiveLocation);
331
332                         if (pageParser.StyleSheetTheme != null)
333                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "StyleSheetTheme", pageParser.StyleSheetTheme), directiveLocation));
334
335                         if (pageParser.Async != false)
336                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncMode", pageParser.Async), directiveLocation));
337
338                         if (pageParser.AsyncTimeout != -1)
339                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncTimeout",
340                                                                                             TimeSpan.FromSeconds (pageParser.AsyncTimeout)), directiveLocation));
341
342                         CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (thisRef, "InitializeCulture");
343                         method.Statements.Add (AddLinePragma (new CodeExpressionStatement (expr), directiveLocation));
344                 }
345 #if NET_4_0
346                 protected override void AddStatementsToInitMethodBottom (ControlBuilder builder, CodeMemberMethod method)
347                 {
348                         ILocation directiveLocation = pageParser.DirectiveLocation;
349                         AssignPropertyWithExpression <string> (method, "MetaDescription", pageParser.MetaDescription, directiveLocation);
350                         AssignPropertyWithExpression <string> (method, "MetaKeywords", pageParser.MetaKeywords, directiveLocation);
351                 }
352 #endif
353                 protected override void PrependStatementsToFrameworkInitialize (CodeMemberMethod method)
354                 {
355                         base.PrependStatementsToFrameworkInitialize (method);
356                         if (pageParser.StyleSheetTheme != null)
357                                 method.Statements.Add (CreatePropertyAssign ("StyleSheetTheme", pageParser.StyleSheetTheme));
358                 }
359                 
360                 protected override void AppendStatementsToFrameworkInitialize (CodeMemberMethod method)
361                 {
362                         base.AppendStatementsToFrameworkInitialize (method);
363
364                         ArrayList deps = pageParser.Dependencies;
365                         int depsCount = deps != null ? deps.Count : 0;
366
367                         if (depsCount > 0) {
368                                 CodeFieldReferenceExpression fileDependencies = GetMainClassFieldReferenceExpression ("__fileDependencies");
369
370                                 method.Statements.Add (
371                                         new CodeMethodInvokeExpression (
372                                                 thisRef,
373                                                 "AddWrappedFileDependencies",
374                                                 new CodeExpression[] {fileDependencies})
375                                 );
376
377                         }
378
379                         if (pageParser.OutputCache) {
380                                 CodeMethodReferenceExpression init = new CodeMethodReferenceExpression (thisRef, "InitOutputCache");
381                                 CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (init, GetMainClassFieldReferenceExpression ("__outputCacheSettings"));
382                                 method.Statements.Add (invoke);
383                         }
384
385                         if (pageParser.ValidateRequest) {
386                                 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
387                                 CodePropertyReferenceExpression prop;
388                                 prop = new CodePropertyReferenceExpression (thisRef, "Request");
389                                 expr.Method = new CodeMethodReferenceExpression (prop, "ValidateInput");
390                                 method.Statements.Add (expr);
391                         }
392                 }
393
394                 CodeAssignStatement AssignOutputCacheParameter (CodeVariableReferenceExpression variable, string propName, object value)
395                 {
396                         var ret = new CodeAssignStatement ();
397
398                         ret.Left = new CodeFieldReferenceExpression (variable, propName);
399
400                         if (value is OutputCacheLocation)
401                                 ret.Right = new CodeFieldReferenceExpression (
402                                         new CodeTypeReferenceExpression (new CodeTypeReference (typeof (OutputCacheLocation), CodeTypeReferenceOptions.GlobalReference)),
403                                         value.ToString ()
404                                 );
405                         else
406                                 ret.Right = new CodePrimitiveExpression (value);
407                         return ret;
408                 }
409                 
410                 void OutputCacheParamsBlock (CodeMemberMethod method)
411                 {
412                         var statements = new List <CodeStatement> ();
413                         var localSettingsDecl = new CodeVariableDeclarationStatement (typeof (OutputCacheParameters), "outputCacheSettings");
414                         var localSettings = new CodeVariableReferenceExpression ("outputCacheSettings");
415                         
416                         statements.Add (localSettingsDecl);
417                         statements.Add (
418                                 new CodeAssignStatement (
419                                         localSettings,
420                                         new CodeObjectCreateExpression (typeof (OutputCacheParameters), new CodeExpression[] {})
421                                 )
422                         );
423                         
424                         TemplateParser.OutputCacheParsedParams parsed = pageParser.OutputCacheParsedParameters;
425                         if ((parsed & TemplateParser.OutputCacheParsedParams.CacheProfile) != 0)
426                                 statements.Add (AssignOutputCacheParameter (localSettings, "CacheProfile", pageParser.OutputCacheCacheProfile));
427                         statements.Add (AssignOutputCacheParameter (localSettings, "Duration", pageParser.OutputCacheDuration));
428                         if ((parsed & TemplateParser.OutputCacheParsedParams.Location) != 0)
429                                 statements.Add (AssignOutputCacheParameter (localSettings, "Location", pageParser.OutputCacheLocation));
430                         if ((parsed & TemplateParser.OutputCacheParsedParams.NoStore) != 0)
431                                 statements.Add (AssignOutputCacheParameter (localSettings, "NoStore", pageParser.OutputCacheNoStore));
432                         if ((parsed & TemplateParser.OutputCacheParsedParams.SqlDependency) != 0)
433                                 statements.Add (AssignOutputCacheParameter (localSettings, "SqlDependency", pageParser.OutputCacheSqlDependency));
434                         if ((parsed & TemplateParser.OutputCacheParsedParams.VaryByContentEncodings) != 0)
435                                 statements.Add (AssignOutputCacheParameter (localSettings, "VaryByContentEncoding", pageParser.OutputCacheVaryByContentEncodings));
436                         if ((parsed & TemplateParser.OutputCacheParsedParams.VaryByControl) != 0)
437                                 statements.Add (AssignOutputCacheParameter (localSettings, "VaryByControl", pageParser.OutputCacheVaryByControls));
438                         if ((parsed & TemplateParser.OutputCacheParsedParams.VaryByCustom) != 0)
439                                 statements.Add (AssignOutputCacheParameter (localSettings, "VaryByCustom", pageParser.OutputCacheVaryByCustom));
440                         if ((parsed & TemplateParser.OutputCacheParsedParams.VaryByHeader) != 0)
441                                 statements.Add (AssignOutputCacheParameter (localSettings, "VaryByHeader", pageParser.OutputCacheVaryByHeader));
442                         statements.Add (AssignOutputCacheParameter (localSettings, "VaryByParam", pageParser.OutputCacheVaryByParam));
443
444                         CodeFieldReferenceExpression outputCacheSettings = GetMainClassFieldReferenceExpression ("__outputCacheSettings");
445                         statements.Add (new CodeAssignStatement (outputCacheSettings, localSettings));
446                         
447                         var cond = new CodeConditionStatement (
448                                 new CodeBinaryOperatorExpression (
449                                         outputCacheSettings,
450                                         CodeBinaryOperatorType.IdentityEquality,
451                                         new CodePrimitiveExpression (null)
452                                 ),
453                                 statements.ToArray ()
454                         );
455
456                         method.Statements.Add (cond);
457                 }
458
459                 void CreateStronglyTypedProperty (Type type, string name)
460                 {
461                         if (type == null)
462                                 return;
463                         
464                         CodeMemberProperty mprop = new CodeMemberProperty ();
465                         mprop.Name = name;
466                         mprop.Type = new CodeTypeReference (type);
467                         mprop.Attributes = MemberAttributes.Public | MemberAttributes.New;
468                         CodeExpression prop = new CodePropertyReferenceExpression (new CodeBaseReferenceExpression (), name);
469                         prop = new CodeCastExpression (type, prop);
470                         mprop.GetStatements.Add (new CodeMethodReturnStatement (prop));
471                         if (partialClass != null)
472                                 partialClass.Members.Add (mprop);
473                         else
474                                 mainClass.Members.Add (mprop);
475
476                         AddReferencedAssembly (type.Assembly);
477                 }
478                 
479                 protected internal override void CreateMethods ()
480                 {
481                         base.CreateMethods ();
482
483                         CreateProfileProperty ();
484                         CreateStronglyTypedProperty (pageParser.MasterType, "Master");
485                         CreateStronglyTypedProperty (pageParser.PreviousPageType, "PreviousPage");
486                         CreateGetTypeHashCode ();
487
488                         if (pageParser.Async)
489                                 CreateAsyncMethods ();
490                 }
491
492                 void CreateAsyncMethods ()
493                 {
494                         CodeMemberMethod method = new CodeMemberMethod ();
495                         CodeParameterDeclarationExpression arg;
496                         CodeMethodInvokeExpression invoke;
497
498                         // public virtual System.IAsyncResult BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object data);
499                         method.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
500                         method.Name = "BeginProcessRequest";
501                         method.Attributes = MemberAttributes.Public;
502                         
503                         arg = new CodeParameterDeclarationExpression ();
504                         arg.Type = new CodeTypeReference (typeof (HttpContext));
505                         arg.Name = "context";
506                         method.Parameters.Add (arg);
507
508                         arg = new CodeParameterDeclarationExpression ();
509                         arg.Type = new CodeTypeReference (typeof (AsyncCallback));
510                         arg.Name = "cb";
511                         method.Parameters.Add (arg);
512
513                         arg = new CodeParameterDeclarationExpression ();
514                         arg.Type = new CodeTypeReference (typeof (object));
515                         arg.Name = "data";
516                         method.Parameters.Add (arg);
517
518                         invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageBeginProcessRequest");
519                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
520                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("cb"));
521                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("data"));
522
523                         method.Statements.Add (new CodeMethodReturnStatement (invoke));
524                         mainClass.Members.Add (method);
525
526                         // public virtual void EndProcessRequest(System.IAsyncResult ar);
527                         method = new CodeMemberMethod ();
528                         method.ReturnType = new CodeTypeReference (typeof (void));
529                         method.Name = "EndProcessRequest";
530                         method.Attributes = MemberAttributes.Public;
531
532                         arg = new CodeParameterDeclarationExpression ();
533                         arg.Type = new CodeTypeReference (typeof (IAsyncResult));
534                         arg.Name = "ar";
535                         method.Parameters.Add (arg);
536
537                         invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageEndProcessRequest");
538                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("ar"));
539
540                         method.Statements.Add (invoke);
541                         mainClass.Members.Add (method);
542
543                         // public override void ProcessRequest(System.Web.HttpContext context);
544                         method = new CodeMemberMethod ();
545                         method.ReturnType = new CodeTypeReference (typeof (void));
546                         method.Name = "ProcessRequest";
547                         method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
548
549                         arg = new CodeParameterDeclarationExpression ();
550                         arg.Type = new CodeTypeReference (typeof (HttpContext));
551                         arg.Name = "context";
552                         method.Parameters.Add (arg);
553                         
554                         invoke = new CodeMethodInvokeExpression (new CodeBaseReferenceExpression (), "ProcessRequest");
555                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
556
557                         method.Statements.Add (invoke);
558                         mainClass.Members.Add (method);
559                 }
560                 
561                 public static Type CompilePageType (PageParser pageParser)
562                 {
563                         PageCompiler compiler = new PageCompiler (pageParser);
564                         return compiler.GetCompiledType ();
565                 }
566         }
567 }