NAnt.DotNet.Tasks.ScriptTask.ExecuteTask C# (CSharp) Method

ExecuteTask() protected method

Executes the script block.
protected ExecuteTask ( ) : void
return void
        protected override void ExecuteTask()
        {
            // create compiler info for user-specified language
            CompilerInfo compilerInfo = CreateCompilerInfo(Language);

            // ensure base directory is set, even if fileset was not initialized
            // from XML
            if (References.BaseDirectory == null) {
                References.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
            }

            ICodeCompiler compiler = compilerInfo.Compiler;
            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false;
            options.GenerateInMemory = true;
            options.MainClass = MainClass;

            // implicitly reference the NAnt.Core assembly
            options.ReferencedAssemblies.Add (typeof (Project).Assembly.Location);

            // Log the assembly being added to the CompilerParameters
            Log(Level.Verbose, "Adding assembly {0}", typeof (Project).Assembly.GetName().Name);

            // add (and load) assemblies specified by user
            foreach (string assemblyFile in References.FileNames) {
                try {
                    // load the assembly into current AppDomain to ensure it is
                    // available when executing the emitted assembly
                    Assembly asm = Assembly.LoadFrom(assemblyFile);

                    // Log the assembly being added to the CompilerParameters
                    Log(Level.Verbose, "Adding assembly {0}", asm.GetName().Name);

                    // add the location of the loaded assembly
                    if (!StringUtils.IsNullOrEmpty(asm.Location)) {
                        options.ReferencedAssemblies.Add(asm.Location);
                    }
                } catch (Exception ex) {
                    throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                        ResourceUtils.GetString("NA2028"), assemblyFile), Location, ex);
                }
            }

            StringCollection imports = new StringCollection();

            foreach (NamespaceImport import in Imports) {
                if (import.IfDefined && !import.UnlessDefined) {
                    imports.Add(import.Namespace);
                }
            }

            // generate the code
            CodeCompileUnit compileUnit = compilerInfo.GenerateCode(_rootClassName,
                Code.Xml.InnerText, imports, Prefix);

            StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);

            compilerInfo.CodeGen.GenerateCodeFromCompileUnit(compileUnit, sw, null);
            string code = sw.ToString();

            Log(Level.Debug, ResourceUtils.GetString("String_GeneratedCodeLooksLike") + "\n{0}", code);

            CompilerResults results = compiler.CompileAssemblyFromDom(options, compileUnit);

            Assembly compiled = null;
            if (results.Errors.Count > 0) {
                string errors = ResourceUtils.GetString("NA2029") + Environment.NewLine;
                foreach (CompilerError err in results.Errors) {
                    errors += err.ToString() + Environment.NewLine;
                }
                errors += code;
                throw new BuildException(errors, Location);
            } else {
                compiled = results.CompiledAssembly;
            }

            // scan the new assembly for tasks, types and functions
            // Its unlikely that tasks will be defined in buildfiles though.
            bool extensionAssembly = TypeFactory.ScanAssembly(compiled, this);

            string mainClass = _rootClassName;
            if (!StringUtils.IsNullOrEmpty(MainClass)) {
                mainClass += "+" + MainClass;
            }

            Type mainType = compiled.GetType(mainClass);
            if (mainType == null) {
                throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                    ResourceUtils.GetString("NA2030"), mainClass), Location);
            }

            MethodInfo entry = mainType.GetMethod("ScriptMain");
            // check for task or function definitions.
            if (entry == null) {
                if (!extensionAssembly) {
                    throw new BuildException(ResourceUtils.GetString("NA2031"), Location);
                } else {
                    return; // no entry point so nothing to do here beyond loading task and function defs
                }
            }

            if (!entry.IsStatic) {
                throw new BuildException(ResourceUtils.GetString("NA2032"), Location);
            }

            ParameterInfo[] entryParams = entry.GetParameters();

            if (entryParams.Length != 1) {
                throw new BuildException(ResourceUtils.GetString("NA2033"), Location);
            }

            if (entryParams[0].ParameterType.FullName != typeof(Project).FullName) {
                throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                    ResourceUtils.GetString("NA2034"), entryParams[0].ParameterType.FullName,
                    typeof(Project).FullName), Location);
            }

            try {
                // invoke Main method
                entry.Invoke(null, new object[] {Project});
            } catch (Exception ex) {
                // this exception is not likely to tell us much, BUT the
                // InnerException normally contains the runtime exception
                // thrown by the executed script code.
                throw new BuildException(ResourceUtils.GetString("NA2035"), Location,
                    ex.InnerException);
            }
        }