// Constructor
        internal ScriptAssembly(ScriptDomain domain, Assembly rawAssembly, CodeSecurityEngine securityEngine, CompilationResult compileResult = null)
        {
            this.domain         = domain;
            this.rawAssembly    = rawAssembly;
            this.securityEngine = securityEngine;
            this.compileResult  = compileResult;

            // Create cached types
            foreach (Type type in rawAssembly.GetTypes())
            {
                scriptTypes.Add(type.FullName, new ScriptType(this, type));
            }
        }
        // Methods
        /// <summary>
        /// Run security verification on this assembly using the specified security restrictions.
        /// </summary>
        /// <param name="restrictions">The restrictions used to verify the assembly</param>
        /// <returns>True if the assembly passes security verification or false if it fails</returns>
        public bool SecurityCheckAssembly(CodeSecurityRestrictions restrictions)
        {
            // Check for already checked
            if (securityEngine == null)
            {
                return(isSecurityValidated);
            }

            // Run code valdiation
            isSecurityValidated = securityEngine.SecurityCheckAssembly(restrictions);

            // Release security engine
            securityEngine = null;

            return(isSecurityValidated);
        }
        /// <summary>
        /// Attempts to load a managed assembly from the specified raw bytes.
        /// Use <see cref="SecurityResult"/> to get the output from the code validation request.
        /// </summary>
        /// <param name="assemblyBytes">The raw data representing the file structure of the managed assembly, The result of <see cref="File.ReadAllBytes(string)"/> for example.</param>
        /// <returns>An instance of <see cref="ScriptAssembly"/> representing the loaded assembly or null if an error occurs</returns>
        /// <param name="securityMode">The security mode which determines whether code validation will run</param>
        public ScriptAssembly LoadAssembly(byte[] assemblyBytes, ScriptSecurityMode securityMode = ScriptSecurityMode.UseSettings)
        {
            // Check for disposed
            CheckDisposed();

            // Load the assembly
            Assembly           assembly       = sandbox.Load(assemblyBytes);
            CodeSecurityEngine securityEngine = null;

            // Create the security engine
            if (assembly != null)
            {
                securityEngine = new CodeSecurityEngine(assemblyBytes);
            }

            // Create script assembly
            return(RegisterAssembly(assembly, securityMode, securityEngine, false));
        }
        /// <summary>
        /// Attempts to load the specified managed assembly into the sandbox app domain.
        /// Use <see cref="SecurityResult"/> to get the output from the code validation request.
        /// </summary>
        /// <param name="name">The <see cref="AssemblyName"/> representing the assembly to load</param>
        /// <param name="securityMode">The security mode which determines whether code validation will run</param>
        /// <returns>An instance of <see cref="ScriptAssembly"/> representing the loaded assembly or null if an error occurs</returns>
        public ScriptAssembly LoadAssembly(AssemblyName name, ScriptSecurityMode securityMode = ScriptSecurityMode.UseSettings)
        {
            // Check for disposed
            CheckDisposed();

            // Load the assembly
            Assembly           assembly       = sandbox.Load(name);
            CodeSecurityEngine securityEngine = null;

            // Initialize security engine
            if (assembly != null)
            {
                securityEngine = new CodeSecurityEngine(assembly.Location);
            }

            // Create script assembly
            return(RegisterAssembly(assembly, securityMode, securityEngine, false));
        }
        /// <summary>
        /// Run security verification on this assembly using the specified security restrictions and output a security report
        /// </summary>
        /// <param name="restrictions">The restrictions used to verify the assembly</param>
        /// <param name="report">The security report generated by the assembly checker</param>
        /// <returns>True if the assembly passes security verification or false if it fails</returns>
        public bool SecurityCheckAssembly(CodeSecurityRestrictions restrictions, out CodeSecurityReport report)
        {
            // Check for already checked
            if (securityEngine == null)
            {
                report = securityReport;
                return(isSecurityValidated);
            }

            // Run code validation
            isSecurityValidated = securityEngine.SecurityCheckAssembly(restrictions, out report);

            // Release security engine and store report
            securityEngine = null;
            securityReport = report;

            return(isSecurityValidated);
        }
        /// <summary>
        /// Compile and load the specified C# source files.
        /// Use <see cref="CompileResult"/> to get the output from the compile request.
        /// Use <see cref="SecurityResult"/> to get the output from the code validation request.
        /// </summary>
        /// <param name="cSharpFiles">An array of filepaths to C# source files</param>
        /// <param name="securityMode">The code validation used to verify the code</param>
        /// <returns>The compiled and loaded assembly or null if the compil or security verification failed</returns>
        public ScriptAssembly CompileAndLoadFiles(string[] cSharpFiles, ScriptSecurityMode securityMode = ScriptSecurityMode.UseSettings, IMetadataReferenceProvider[] additionalReferenceAssemblies = null)
        {
            // Make sure the compiler is initialized and the domain is valid
            CheckDisposed();
            CheckCompiler();

            lock (this)
            {
                // Compile from file
                compileResult = sharedCompiler.CompileFromFiles(cSharpFiles, additionalReferenceAssemblies);

                // Log to console
                LogCompilerOutputToConsole();

                // Create the security engine
                CodeSecurityEngine securityEngine = CreateSecurityEngine(compileResult);

                // Security check
                return(RegisterAssembly(compileResult.OutputAssembly, securityMode, securityEngine, true, compileResult));
            }
        }
        /// <summary>
        /// Run security verification on this assembly using the specified security restrictions and output a security report
        /// </summary>
        /// <param name="restrictions">The restrictions used to verify the assembly</param>
        /// <param name="report">The security report generated by the assembly checker</param>
        /// <returns>True if the assembly passes security verification or false if it fails</returns>
        public bool SecurityCheckAssembly(CodeSecurityRestrictions restrictions, out CodeSecurityReport report)
        {
            // Skip checks
            if (isSecurityValidated == true && restrictions.RestrictionsHash == securityValidatedHash)
            {
                report = securityReport;
                return(true);
            }

            // Create the security engine
            CodeSecurityEngine securityEngine = CreateSecurityEngine();

            // Check for already checked
            if (securityEngine == null)
            {
                report = securityReport;
                return(isSecurityValidated);
            }

            // Must dispose once finished
            using (securityEngine)
            {
                // Run code valdiation
                isSecurityValidated = securityEngine.SecurityCheckAssembly(restrictions, out securityReport);

                // Check for verified
                if (isSecurityValidated == true)
                {
                    // Store the hash so that the same restirctions will not need to run again
                    securityValidatedHash = restrictions.RestrictionsHash;
                }
                else
                {
                    securityValidatedHash = -1;
                }

                report = securityReport;
                return(isSecurityValidated);
            }
        }
        /// <summary>
        /// Attempts to load the specified managed assembly into the sandbox app domain.
        /// Use <see cref="SecurityResult"/> to get the output from the code validation request.
        /// </summary>
        /// <param name="fullPath">The full path the the .dll file</param>
        /// <param name="securityMode">The security mode which determines whether code validation will run</param>
        /// <returns>An instance of <see cref="ScriptAssembly"/> representing the loaded assembly or null if an error occurs</returns>
        public ScriptAssembly LoadAssembly(string fullPath, ScriptSecurityMode securityMode = ScriptSecurityMode.UseSettings)
        {
            // Check for disposed
            CheckDisposed();

            // Create an assembly name object
            AssemblyName name = AssemblyName.GetAssemblyName(fullPath);// new AssemblyName();
            //name.CodeBase = fullPath;

            // Load the assembly
            Assembly           assembly       = sandbox.Load(name);
            CodeSecurityEngine securityEngine = null;

            // Create the security engine
            if (fullPath != null)
            {
                securityEngine = new CodeSecurityEngine(fullPath);
            }

            // Create script assembly
            return(RegisterAssembly(assembly, securityMode, securityEngine, false));
        }
        private ScriptAssembly RegisterAssembly(Assembly assembly, ScriptSecurityMode securityMode, CodeSecurityEngine securityEngine, bool isRuntimeCompiled, CompilationResult compileResult = null)
        {
            // Check for error
            if (assembly == null)
            {
                return(null);
            }

            // Reset report
            securityResult = null;

            // Create script assembly
            ScriptAssembly scriptAssembly = new ScriptAssembly(this, assembly, securityEngine, compileResult);

            // Check for ensure security mode
            bool performSecurityCheck = (securityMode == ScriptSecurityMode.EnsureSecurity);

            // Get value from settings
            if (securityMode == ScriptSecurityMode.UseSettings)
            {
                performSecurityCheck = RoslynCSharp.Settings.SecurityCheckCode;
            }

            // Check for security checks
            if (performSecurityCheck == true)
            {
                // Perform code validation
                if (scriptAssembly.SecurityCheckAssembly(RoslynCSharp.Settings.SecurityRestrictions, out securityResult) == false)
                {
                    // Log the error
                    RoslynCSharp.LogError(securityResult.GetSummaryText());
                    RoslynCSharp.LogError(securityResult.GetAllText(true));
                    // Dont load the assembly
                    return(null);
                }
                else
                {
                    RoslynCSharp.Log(securityResult.GetSummaryText());
                }
            }

            // Mark as runtime compiled
            if (isRuntimeCompiled == true)
            {
                scriptAssembly.MarkAsRuntimeCompiled();
            }

            lock (this)
            {
                // Register with domain
                this.loadedAssemblies.Add(scriptAssembly);
            }

            // Return result
            return(scriptAssembly);
        }