private Assembly CompileAssembly(List <ScriptClass> scriptsForLang)
{
TempFileCollection allTempFiles = compiler.CompilerResults.TempFiles;
CompilerErrorCollection allErrors = compiler.CompilerResults.Errors;
ScriptClass lastScript = scriptsForLang[scriptsForLang.Count - 1];
CodeDomProvider provider;
bool isVB = false;
try {
provider = lastScript.compilerInfo.CreateProvider();
}
catch (ConfigurationException e) {
// The CodeDom provider type could not be located, or some error in machine.config
allErrors.Add(compiler.CreateError(lastScript.EndLineInfo, /*[XT_041]*/ Res.Xslt_ScriptCompileException, e.Message));
return(null);
}
#if !FEATURE_PAL // visualbasic
isVB = provider is Microsoft.VisualBasic.VBCodeProvider;
#endif // !FEATURE_PAL
CodeCompileUnit[] codeUnits = new CodeCompileUnit[scriptsForLang.Count];
CompilerParameters compilParams = lastScript.compilerInfo.CreateDefaultCompilerParameters();
//
compilParams.ReferencedAssemblies.Add(typeof(System.Xml.Res).Assembly.Location);
compilParams.ReferencedAssemblies.Add("System.dll");
if (isVB)
{
compilParams.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
}
bool refAssembliesByHref = false;
for (int idx = 0; idx < scriptsForLang.Count; idx++)
{
ScriptClass script = scriptsForLang[idx];
CodeNamespace scriptNs = new CodeNamespace(ScriptClassesNamespace);
// Add imported namespaces
foreach (string ns in defaultNamespaces)
{
scriptNs.Imports.Add(new CodeNamespaceImport(ns));
}
if (isVB)
{
scriptNs.Imports.Add(new CodeNamespaceImport("Microsoft.VisualBasic"));
}
foreach (string ns in script.nsImports)
{
scriptNs.Imports.Add(new CodeNamespaceImport(ns));
}
scriptNs.Types.Add(script.typeDecl);
CodeCompileUnit unit = new CodeCompileUnit(); {
unit.Namespaces.Add(scriptNs);
if (isVB)
{
// This settings have sense for Visual Basic only. In future releases we may allow to specify
// them explicitly in the msxsl:script element.
unit.UserData["AllowLateBound"] = true; // Allow variables to be declared untyped
unit.UserData["RequireVariableDeclaration"] = false; // Allow variables to be undeclared
}
// Put SecurityTransparentAttribute and SecurityRulesAttribute on the first CodeCompileUnit only
if (idx == 0)
{
unit.AssemblyCustomAttributes.Add(new CodeAttributeDeclaration("System.Security.SecurityTransparentAttribute"));
// We want the assemblies generated for scripts to stick to the old security model
unit.AssemblyCustomAttributes.Add(
new CodeAttributeDeclaration(
new CodeTypeReference(typeof(System.Security.SecurityRulesAttribute)),
new CodeAttributeArgument(
new CodeFieldReferenceExpression(
new CodeTypeReferenceExpression(typeof(System.Security.SecurityRuleSet)), "Level1"))));
}
}
codeUnits[idx] = unit;
foreach (string name in script.refAssemblies)
{
compilParams.ReferencedAssemblies.Add(name);
}
refAssembliesByHref |= script.refAssembliesByHref;
}
XsltSettings settings = compiler.Settings;
compilParams.WarningLevel = settings.WarningLevel >= 0 ? settings.WarningLevel : compilParams.WarningLevel;
compilParams.TreatWarningsAsErrors = settings.TreatWarningsAsErrors;
compilParams.IncludeDebugInformation = compiler.IsDebug;
string asmPath = compiler.ScriptAssemblyPath;
if (asmPath != null && scriptsForLang.Count < scriptClasses.Count)
{
asmPath = Path.ChangeExtension(asmPath, "." + GetLanguageName(lastScript.compilerInfo) + Path.GetExtension(asmPath));
}
compilParams.OutputAssembly = asmPath;
string tempDir = (settings.TempFiles != null) ? settings.TempFiles.TempDir : null;
compilParams.TempFiles = new TempFileCollection(tempDir);
// We need only .dll and .pdb, but there is no way to specify that
bool keepFiles = (compiler.IsDebug && asmPath == null);
#if DEBUG
keepFiles = keepFiles || XmlILTrace.IsEnabled;
#endif
keepFiles = keepFiles && !settings.CheckOnly;
compilParams.TempFiles.KeepFiles = keepFiles;
// If GenerateInMemory == true, then CodeDom loads the compiled assembly using Assembly.Load(byte[])
// instead of Assembly.Load(AssemblyName). That means the assembly will be loaded in the anonymous
// context (http://blogs.msdn.com/Microsoft/archive/2003/05/29/57143.aspx), and its dependencies can only
// be loaded from the Load context or using AssemblyResolve event. However we want to use the LoadFrom
// context to preload all dependencies specified by <ms:assembly href="uri-reference"/>, so we turn off
// GenerateInMemory here.
compilParams.GenerateInMemory = (asmPath == null && !compiler.IsDebug && !refAssembliesByHref) || settings.CheckOnly;
CompilerResults results;
try {
results = provider.CompileAssemblyFromDom(compilParams, codeUnits);
}
catch (ExternalException e) {
// Compiler might have created temporary files
results = new CompilerResults(compilParams.TempFiles);
results.Errors.Add(compiler.CreateError(lastScript.EndLineInfo, /*[XT_041]*/ Res.Xslt_ScriptCompileException, e.Message));
}
if (!settings.CheckOnly)
{
foreach (string fileName in results.TempFiles)
{
allTempFiles.AddFile(fileName, allTempFiles.KeepFiles);
}
}
foreach (CompilerError error in results.Errors)
{
FixErrorPosition(error, scriptsForLang);
compiler.AddModule(error.FileName);
}
allErrors.AddRange(results.Errors);
return(results.Errors.HasErrors ? null : results.CompiledAssembly);
}