2 // System.Web.Compilation.PageCompiler
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
32 using System.Collections;
34 using System.Reflection;
36 using System.Web.Configuration;
38 using System.Web.SessionState;
39 using System.Web.Util;
41 using System.Web.Profile;
44 namespace System.Web.Compilation
46 class PageCompiler : TemplateControlCompiler
48 PageParser pageParser;
49 static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
51 public PageCompiler (PageParser pageParser)
54 this.pageParser = pageParser;
58 protected override void CreateStaticFields ()
60 base.CreateStaticFields ();
62 CodeMemberField fld = new CodeMemberField (typeof (object), "__fileDependencies");
63 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
64 fld.InitExpression = new CodePrimitiveExpression (null);
65 mainClass.Members.Add (fld);
69 protected override void CreateConstructor (CodeStatementCollection localVars,
70 CodeStatementCollection trueStmt)
72 if (pageParser.ClientTarget != null) {
74 prop = new CodePropertyReferenceExpression (thisRef, "ClientTarget");
75 CodeExpression ct = new CodePrimitiveExpression (pageParser.ClientTarget);
76 if (localVars == null)
77 localVars = new CodeStatementCollection ();
78 localVars.Add (new CodeAssignStatement (prop, ct));
82 ArrayList deps = pageParser.Dependencies;
83 int depsCount = deps != null ? deps.Count : 0;
86 if (localVars == null)
87 localVars = new CodeStatementCollection ();
89 trueStmt = new CodeStatementCollection ();
92 new CodeVariableDeclarationStatement (
97 CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
99 new CodeAssignStatement (dependencies, new CodeArrayCreateExpression (typeof (string), depsCount))
102 CodeArrayIndexerExpression arrayIndex;
103 CodeAssignStatement assign;
106 for (int i = 0; i < depsCount; i++) {
108 arrayIndex = new CodeArrayIndexerExpression (dependencies, new CodeExpression[] {new CodePrimitiveExpression (i)});
109 assign = new CodeAssignStatement (arrayIndex, new CodePrimitiveExpression (o));
110 trueStmt.Add (assign);
113 CodeMethodInvokeExpression getDepsCall = new CodeMethodInvokeExpression (
115 "GetWrappedFileDependencies",
116 new CodeExpression[] {dependencies}
119 assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), getDepsCall);
120 trueStmt.Add (assign);
123 base.CreateConstructor (localVars, trueStmt);
126 protected override void AddInterfaces ()
128 base.AddInterfaces ();
129 CodeTypeReference cref;
131 if (pageParser.EnableSessionState) {
132 cref = new CodeTypeReference (typeof (IRequiresSessionState));
134 if (partialClass != null)
135 partialClass.BaseTypes.Add (cref);
138 mainClass.BaseTypes.Add (cref);
141 if (pageParser.ReadOnlySessionState) {
142 cref = new CodeTypeReference (typeof (IReadOnlySessionState));
144 if (partialClass != null)
145 partialClass.BaseTypes.Add (cref);
148 mainClass.BaseTypes.Add (cref);
152 if (pageParser.Async)
153 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpAsyncHandler)));
155 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpHandler)));
159 void CreateGetTypeHashCode ()
161 CodeMemberMethod method = new CodeMemberMethod ();
162 method.ReturnType = intRef;
163 method.Name = "GetTypeHashCode";
164 method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
165 Random rnd = new Random (pageParser.InputFile.GetHashCode ());
166 method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
167 mainClass.Members.Add (method);
170 static CodeAssignStatement CreatePropertyAssign (CodeExpression expr, string name, object value)
172 CodePropertyReferenceExpression prop;
173 prop = new CodePropertyReferenceExpression (expr, name);
174 CodePrimitiveExpression prim;
175 prim = new CodePrimitiveExpression (value);
176 return new CodeAssignStatement (prop, prim);
179 static CodeAssignStatement CreatePropertyAssign (string name, object value)
181 return CreatePropertyAssign (thisRef, name, value);
184 protected override void AddStatementsToInitMethod (CodeMemberMethod method)
187 ILocation directiveLocation = pageParser.DirectiveLocation;
189 CodeArgumentReferenceExpression ctrlVar = new CodeArgumentReferenceExpression("__ctrl");
190 if (pageParser.Title != null)
191 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Title", pageParser.Title), directiveLocation));
193 if (pageParser.MasterPageFile != null)
194 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "MasterPageFile", pageParser.MasterPageFile), directiveLocation));
196 if (pageParser.Theme != null)
197 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Theme", pageParser.Theme), directiveLocation));
199 if (pageParser.StyleSheetTheme != null)
200 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "StyleSheetTheme", pageParser.StyleSheetTheme), directiveLocation));
202 if (pageParser.Async != false)
203 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncMode", pageParser.Async), directiveLocation));
205 if (pageParser.AsyncTimeout != -1)
206 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncTimeout",
207 TimeSpan.FromSeconds (pageParser.AsyncTimeout)), directiveLocation));
209 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (thisRef, "InitializeCulture");
210 method.Statements.Add (AddLinePragma (new CodeExpressionStatement (expr), directiveLocation));
214 protected override void PrependStatementsToFrameworkInitialize (CodeMemberMethod method)
216 base.PrependStatementsToFrameworkInitialize (method);
218 if (pageParser.StyleSheetTheme != null)
219 method.Statements.Add (CreatePropertyAssign ("StyleSheetTheme", pageParser.StyleSheetTheme));
223 protected override void AppendStatementsToFrameworkInitialize (CodeMemberMethod method)
225 base.AppendStatementsToFrameworkInitialize (method);
228 ArrayList deps = pageParser.Dependencies;
229 int depsCount = deps != null ? deps.Count : 0;
232 CodeFieldReferenceExpression fileDependencies = GetMainClassFieldReferenceExpression ("__fileDependencies");
234 method.Statements.Add (
235 new CodeMethodInvokeExpression (
237 "AddWrappedFileDependencies",
238 new CodeExpression[] {fileDependencies})
243 string responseEncoding = pageParser.ResponseEncoding;
244 if (responseEncoding != null)
245 method.Statements.Add (CreatePropertyAssign ("ResponseEncoding", responseEncoding));
247 int codepage = pageParser.CodePage;
249 method.Statements.Add (CreatePropertyAssign ("CodePage", codepage));
251 string contentType = pageParser.ContentType;
252 if (contentType != null)
253 method.Statements.Add (CreatePropertyAssign ("ContentType", contentType));
255 if (pageParser.OutputCache) {
256 CodeMethodReferenceExpression init = new CodeMethodReferenceExpression (null,
258 CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (init,
259 OutputCacheParams ());
260 method.Statements.Add (invoke);
263 int lcid = pageParser.LCID;
265 method.Statements.Add (CreatePropertyAssign ("LCID", lcid));
267 string culture = pageParser.Culture;
269 method.Statements.Add (CreatePropertyAssign ("Culture", culture));
271 culture = pageParser.UICulture;
273 method.Statements.Add (CreatePropertyAssign ("UICulture", culture));
275 string errorPage = pageParser.ErrorPage;
276 if (errorPage != null)
277 method.Statements.Add (CreatePropertyAssign ("ErrorPage", errorPage));
279 if (pageParser.HaveTrace) {
280 CodeAssignStatement stmt = new CodeAssignStatement ();
281 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceEnabled");
282 stmt.Right = new CodePrimitiveExpression (pageParser.Trace);
283 method.Statements.Add (stmt);
286 if (pageParser.TraceMode != TraceMode.Default) {
287 CodeAssignStatement stmt = new CodeAssignStatement ();
288 CodeTypeReferenceExpression tm = new CodeTypeReferenceExpression ("System.Web.TraceMode");
289 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceModeValue");
290 stmt.Right = new CodeFieldReferenceExpression (tm, pageParser.TraceMode.ToString ());
291 method.Statements.Add (stmt);
294 if (pageParser.NotBuffer) {
295 CodeAssignStatement stmt = new CodeAssignStatement ();
296 stmt.Left = new CodePropertyReferenceExpression (thisRef, "Buffer");
297 stmt.Right = new CodePrimitiveExpression (false);
298 method.Statements.Add (stmt);
302 if (pageParser.ValidateRequest) {
303 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
304 CodePropertyReferenceExpression prop;
305 prop = new CodePropertyReferenceExpression (thisRef, "Request");
306 expr.Method = new CodeMethodReferenceExpression (prop, "ValidateInput");
307 method.Statements.Add (expr);
311 if (!pageParser.EnableEventValidation) {
312 CodeAssignStatement stmt = new CodeAssignStatement ();
313 CodePropertyReferenceExpression prop;
314 prop = new CodePropertyReferenceExpression (thisRef, "EnableEventValidation");
316 stmt.Right = new CodePrimitiveExpression (pageParser.EnableEventValidation);
317 method.Statements.Add (stmt);
320 if (pageParser.MaintainScrollPositionOnPostBack) {
321 CodeAssignStatement stmt = new CodeAssignStatement ();
322 CodePropertyReferenceExpression prop;
323 prop = new CodePropertyReferenceExpression (thisRef, "MaintainScrollPositionOnPostBack");
325 stmt.Right = new CodePrimitiveExpression (pageParser.MaintainScrollPositionOnPostBack);
326 method.Statements.Add (stmt);
331 private CodeExpression[] OutputCacheParams ()
333 return new CodeExpression [] {
334 new CodePrimitiveExpression (pageParser.OutputCacheDuration),
336 new CodePrimitiveExpression (pageParser.OutputCacheVaryByContentEncodings),
338 new CodePrimitiveExpression (pageParser.OutputCacheVaryByHeader),
339 new CodePrimitiveExpression (pageParser.OutputCacheVaryByCustom),
340 new CodeSnippetExpression (typeof (OutputCacheLocation).ToString () +
341 "." + pageParser.OutputCacheLocation.ToString ()),
342 new CodePrimitiveExpression (pageParser.OutputCacheVaryByParam)
347 void CreateStronglyTypedProperty (Type type, string name)
352 CodeMemberProperty mprop = new CodeMemberProperty ();
354 mprop.Type = new CodeTypeReference (type);
355 mprop.Attributes = MemberAttributes.Public | MemberAttributes.New;
356 CodeExpression prop = new CodePropertyReferenceExpression (new CodeBaseReferenceExpression (), name);
357 prop = new CodeCastExpression (type, prop);
358 mprop.GetStatements.Add (new CodeMethodReturnStatement (prop));
359 if (partialClass != null)
360 partialClass.Members.Add (mprop);
362 mainClass.Members.Add (mprop);
366 protected internal override void CreateMethods ()
368 base.CreateMethods ();
371 CreateProfileProperty ();
372 CreateStronglyTypedProperty (pageParser.MasterType, "Master");
373 CreateStronglyTypedProperty (pageParser.PreviousPageType, "PreviousPage");
376 CreateGetTypeHashCode ();
379 if (pageParser.Async)
380 CreateAsyncMethods ();
385 void CreateAsyncMethods ()
387 CodeMemberMethod method = new CodeMemberMethod ();
388 CodeParameterDeclarationExpression arg;
389 CodeMethodInvokeExpression invoke;
391 // public virtual System.IAsyncResult BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object data);
392 method.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
393 method.Name = "BeginProcessRequest";
394 method.Attributes = MemberAttributes.Public;
396 arg = new CodeParameterDeclarationExpression ();
397 arg.Type = new CodeTypeReference (typeof (HttpContext));
398 arg.Name = "context";
399 method.Parameters.Add (arg);
401 arg = new CodeParameterDeclarationExpression ();
402 arg.Type = new CodeTypeReference (typeof (AsyncCallback));
404 method.Parameters.Add (arg);
406 arg = new CodeParameterDeclarationExpression ();
407 arg.Type = new CodeTypeReference (typeof (object));
409 method.Parameters.Add (arg);
411 invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageBeginProcessRequest");
412 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
413 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("cb"));
414 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("data"));
416 method.Statements.Add (new CodeMethodReturnStatement (invoke));
417 mainClass.Members.Add (method);
419 // public virtual void EndProcessRequest(System.IAsyncResult ar);
420 method = new CodeMemberMethod ();
421 method.ReturnType = new CodeTypeReference (typeof (void));
422 method.Name = "EndProcessRequest";
423 method.Attributes = MemberAttributes.Public;
425 arg = new CodeParameterDeclarationExpression ();
426 arg.Type = new CodeTypeReference (typeof (IAsyncResult));
428 method.Parameters.Add (arg);
430 invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageEndProcessRequest");
431 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("ar"));
433 method.Statements.Add (invoke);
434 mainClass.Members.Add (method);
436 // public override void ProcessRequest(System.Web.HttpContext context);
437 method = new CodeMemberMethod ();
438 method.ReturnType = new CodeTypeReference (typeof (void));
439 method.Name = "ProcessRequest";
440 method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
442 arg = new CodeParameterDeclarationExpression ();
443 arg.Type = new CodeTypeReference (typeof (HttpContext));
444 arg.Name = "context";
445 method.Parameters.Add (arg);
447 invoke = new CodeMethodInvokeExpression (new CodeBaseReferenceExpression (), "ProcessRequest");
448 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
450 method.Statements.Add (invoke);
451 mainClass.Members.Add (method);
455 public static Type CompilePageType (PageParser pageParser)
457 PageCompiler compiler = new PageCompiler (pageParser);
458 return compiler.GetCompiledType ();