1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
//------------------------------------------------------------------------------
// <copyright file="BaseTemplateBuildProvider.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Compilation {
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Util;
using System.Web.UI;
internal abstract class BaseTemplateBuildProvider: InternalBuildProvider {
private TemplateParser _parser;
internal TemplateParser Parser { get { return _parser; } }
internal override IAssemblyDependencyParser AssemblyDependencyParser {
get { return _parser; }
}
private string _instantiatableFullTypeName;
private string _intermediateFullTypeName;
protected abstract TemplateParser CreateParser();
internal abstract BaseCodeDomTreeGenerator CreateCodeDomTreeGenerator(TemplateParser parser);
protected internal override CodeCompileUnit GetCodeCompileUnit(out IDictionary linePragmasTable) {
Debug.Assert(_parser != null);
// Return the provider type and compiler params
Type codeDomProviderType = _parser.CompilerType.CodeDomProviderType;
// Create a code generator for the language
CodeDomProvider codeDomProvider = CompilationUtil.CreateCodeDomProviderNonPublic(
codeDomProviderType);
// Create a designer mode codedom tree for the page
BaseCodeDomTreeGenerator treeGenerator = CreateCodeDomTreeGenerator(_parser);
treeGenerator.SetDesignerMode();
CodeCompileUnit ccu = treeGenerator.GetCodeDomTree(codeDomProvider,
new StringResourceBuilder(), VirtualPathObject);
linePragmasTable = treeGenerator.LinePragmasTable;
// This code is used to see the full generated code in the debugger. Just uncomment and look at
// generatedCode in the debugger. Don't check in with this code uncommented!
#if TESTCODE
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.Unicode);
codeDomProvider.GenerateCodeFromCompileUnit(ccu, writer, null /*CodeGeneratorOptions*/);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
TextReader reader = new StreamReader(stream);
string generatedCode = reader.ReadToEnd();
#endif
return ccu;
}
public override CompilerType CodeCompilerType {
get {
Debug.Assert(_parser == null);
_parser = CreateParser();
if (IgnoreParseErrors)
_parser.IgnoreParseErrors = true;
if (IgnoreControlProperties)
_parser.IgnoreControlProperties = true;
if (!ThrowOnFirstParseError)
_parser.ThrowOnFirstParseError = false;
_parser.Parse(ReferencedAssemblies, VirtualPathObject);
// If the page is non-compiled, don't ask for a language
if (!Parser.RequiresCompilation)
return null;
return _parser.CompilerType;
}
}
internal override ICollection GetCompileWithDependencies() {
// If there is a code besides file, return it
if (_parser.CodeFileVirtualPath == null)
return null;
// no-compile pages should not have any compile with dependencies
Debug.Assert(Parser.RequiresCompilation);
return new SingleObjectCollection(_parser.CodeFileVirtualPath);
}
public override void GenerateCode(AssemblyBuilder assemblyBuilder) {
// Don't generate any code for no-compile pages
if (!Parser.RequiresCompilation)
return;
BaseCodeDomTreeGenerator treeGenerator = CreateCodeDomTreeGenerator(_parser);
CodeCompileUnit ccu = treeGenerator.GetCodeDomTree(assemblyBuilder.CodeDomProvider,
assemblyBuilder.StringResourceBuilder, VirtualPathObject);
if (ccu != null) {
// Add all the assemblies
if (_parser.AssemblyDependencies != null) {
foreach (Assembly assembly in _parser.AssemblyDependencies) {
assemblyBuilder.AddAssemblyReference(assembly, ccu);
}
}
assemblyBuilder.AddCodeCompileUnit(this, ccu);
}
// Get the name of the generated type that can be instantiated. It may be null
// in updatable compilation scenarios.
_instantiatableFullTypeName = treeGenerator.GetInstantiatableFullTypeName();
// tell the assembly builder to generate a fast factory for this type
if (_instantiatableFullTypeName != null)
assemblyBuilder.GenerateTypeFactory(_instantiatableFullTypeName);
_intermediateFullTypeName = treeGenerator.GetIntermediateFullTypeName();
}
public override Type GetGeneratedType(CompilerResults results) {
return GetGeneratedType(results, useDelayLoadTypeIfEnabled: false);
}
internal Type GetGeneratedType(CompilerResults results, bool useDelayLoadTypeIfEnabled) {
// No Type is generated for no-compile pages
if (!Parser.RequiresCompilation)
return null;
// Figure out the Type that needs to be persisted
string typeName;
if (_instantiatableFullTypeName == null) {
if (Parser.CodeFileVirtualPath != null) {
// Updatable precomp of a code separation page: use the intermediate type
typeName = _intermediateFullTypeName;
}
else {
// Updatable precomp of a single page: use the base type, since nothing got compiled
return Parser.BaseType;
}
}
else {
typeName = _instantiatableFullTypeName;
}
Debug.Assert(typeName != null);
Type generatedType;
if (useDelayLoadTypeIfEnabled && DelayLoadType.Enabled) {
string assemblyFilename = Path.GetFileName(results.PathToAssembly);
string assemblyName = Util.GetAssemblyNameFromFileName(assemblyFilename);
generatedType = new DelayLoadType(assemblyName, typeName);
}
else {
generatedType = results.CompiledAssembly.GetType(typeName);
}
// It should always extend the required base type
// Note: removing this assert as advanced ControlBuilder scenarios allow changing the base type
//Debug.Assert(Parser.BaseType.IsAssignableFrom(generatedType));
return generatedType;
}
internal override BuildResultCompiledType CreateBuildResult(Type t) {
return new BuildResultCompiledTemplateType(t);
}
public override ICollection VirtualPathDependencies {
get {
return _parser.SourceDependencies;
}
}
internal override ICollection GetGeneratedTypeNames() {
if (_parser.GeneratedClassName == null && _parser.BaseTypeName == null) {
return null;
}
ArrayList collection = new ArrayList();
if (_parser.GeneratedClassName != null) {
collection.Add(_parser.GeneratedClassName);
}
if (_parser.BaseTypeName != null) {
collection.Add(Util.MakeFullTypeName(_parser.BaseTypeNamespace, _parser.BaseTypeName));
}
return collection;
}
}
}
|