internal Assembly GetOrLoad(ModuleData moduleData, bool reflectionOnly)
        {
            var cache = reflectionOnly ? _reflectionOnlyAssemblyCache : _assemblyCache;

            lock (s_guard)
            {
                Assembly assembly;
                if (cache.TryGetValue(moduleData.Mvid, out assembly))
                {
                    return assembly;
                }

                var loadedAssembly = RuntimeAssemblyManager.LoadAsAssembly(moduleData.SimpleName, moduleData.Image, reflectionOnly);

                // Validate the loaded assembly matches the value that we now have in the cache. 
                if (!cache.TryGetValue(moduleData.Mvid, out assembly))
                {
                    throw new Exception("Explicit assembly load didn't update the proper cache");
                }

                if (loadedAssembly != assembly)
                {
                    throw new Exception("Cache entry doesn't match result of load");
                }

                return assembly;
            }
        }
        private void CreateAssemblyManager(IEnumerable<ModuleData> compilationDependencies, ModuleData mainModule)
        {
            var allModules = compilationDependencies;
            if (additionalDependencies != null)
            {
                allModules = allModules.Concat(additionalDependencies);
            }

            // We need to add the main module so that it gets checked against already loaded assembly names.
            // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name
            // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain.
            if (mainModule != null)
            {
                allModules = allModules.Concat(new[] { mainModule });
            }

            allModules = allModules.ToArray();

            string conflict = DetectNameCollision(allModules);
            if (conflict != null)
            {
                Type appDomainProxyType = typeof(RuntimeAssemblyManager);
                Assembly thisAssembly = appDomainProxyType.Assembly;

                AppDomain appDomain = null;
                RuntimeAssemblyManager manager;
                try
                {   
                    appDomain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, AppDomain.CurrentDomain.BaseDirectory, null, false);
                    manager = (RuntimeAssemblyManager)appDomain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName);
                }
                catch
                {
                    if (appDomain != null)
                    {
                        AppDomain.Unload(appDomain);
                    }
                    throw;
                }

                this.domain = appDomain;
                this.assemblyManager = manager;
            }
            else
            {
                this.assemblyManager = new RuntimeAssemblyManager();
            }

            this.assemblyManager.AddModuleData(allModules);

            if (mainModule != null)
            {
                this.assemblyManager.AddMainModuleMvid(mainModule.Mvid);
            }
        }
        /// <summary>
        /// Emit all of the references which are not directly or indirectly a <see cref="Compilation"/> value.
        /// </summary>
        internal static void EmitReferences(Compilation compilation, HashSet<string> fullNameSet, List<ModuleData> dependencies, DiagnosticBag diagnostics)
        {
            // NOTE: specifically don't need to consider previous submissions since they will always be compilations.
            foreach (var metadataReference in compilation.References)
            {
                if (metadataReference is CompilationReference)
                {
                    continue;
                }

                var peRef = (PortableExecutableReference)metadataReference;
                var metadata = peRef.GetMetadataNoCopy();
                var isManifestModule = peRef.Properties.Kind == MetadataImageKind.Assembly;
                var identity = isManifestModule
                    ? ((AssemblyMetadata)metadata).GetAssembly().Identity
                    : null;

                // If this is an indirect reference to a Compilation then it is already been emitted 
                // so no more work to be done.
                if (isManifestModule && fullNameSet.Contains(identity.GetDisplayName()))
                {
                    continue;
                }

                foreach (var module in EnumerateModules(metadata))
                {
                    ImmutableArray<byte> bytes = module.Module.PEReaderOpt.GetEntireImage().GetContent();
                    ModuleData moduleData;
                    if (isManifestModule)
                    {
                        fullNameSet.Add(identity.GetDisplayName());
                        moduleData = new ModuleData(identity,
                                                    OutputKind.DynamicallyLinkedLibrary,
                                                    bytes,
                                                    pdb: default(ImmutableArray<byte>),
                                                    inMemoryModule: true);
                    }
                    else
                    {
                        moduleData = new ModuleData(module.Name,
                                                    bytes,
                                                    pdb: default(ImmutableArray<byte>),
                                                    inMemoryModule: true);
                    }

                    dependencies.Add(moduleData);
                    isManifestModule = false;
                }
            }
        }
        internal static EmitOutput? EmitCompilation(
            Compilation compilation,
            IEnumerable<ResourceDescription> manifestResources,
            List<ModuleData> dependencies,
            DiagnosticBag diagnostics,
            CompilationTestData testData
        )
        {
            // A Compilation can appear multiple times in a depnedency graph as both a Compilation and as a MetadataReference
            // value.  Iterate the Compilations eagerly so they are always emitted directly and later references can re-use 
            // the value.  This gives better, and consistent, diagostic information.
            var referencedCompilations = FindReferencedCompilations(compilation);
            var fullNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

            foreach (var referencedCompilation in referencedCompilations)
            {
                var emitData = RuntimeUtilities.EmitCompilationCore(referencedCompilation, null, diagnostics, null);
                if (emitData.HasValue)
                {
                    var moduleData = new ModuleData(referencedCompilation.Assembly.Identity,
                                                    OutputKind.DynamicallyLinkedLibrary,
                                                    emitData.Value.Assembly,
                                                    pdb: default(ImmutableArray<byte>),
                                                    inMemoryModule: true);
                    fullNameSet.Add(moduleData.Id.FullName);
                    dependencies.Add(moduleData);
                }
            }

            // Now that the Compilation values have been emitted, emit the non-compilation references
            foreach (var current in (new[] { compilation }).Concat(referencedCompilations))
            {
                EmitReferences(current, fullNameSet, dependencies, diagnostics);
            }

            return RuntimeUtilities.EmitCompilationCore(compilation, manifestResources, diagnostics, testData);
        }
        public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, bool emitPdb)
        {
            var diagnostics = DiagnosticBag.GetInstance();
            var dependencies = new List<ModuleData>();

            testData.Methods.Clear();

            ImmutableArray<byte> mainImage, mainPdb;
            bool succeeded = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, emitPdb, testData, out mainImage, out mainPdb);

            this.lazyDiagnostics = diagnostics.ToReadOnlyAndFree();

            if (succeeded)
            {
                this.mainModule = new ModuleData(mainCompilation.Assembly.Identity, mainCompilation.Options.OutputKind, mainImage, mainPdb, inMemoryModule: true);
                this.allModuleData = dependencies;
                this.allModuleData.Insert(0, mainModule);
                this.assemblyManager = CreateAssemblyManager(dependencies, mainModule);
            }
            else
            {
                string dumpDir;
                RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir);

                // This method MUST throw if compilation did not succeed.  If compilation succeeded and there were errors, that is bad.
                // Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure.
                throw new EmitException(this.lazyDiagnostics, dumpDir); // ToArray for serializability.
            }
        }
 internal AssemblyData(ModuleData moduleData)
 {
     ModuleData = moduleData;
     Assembly = null;
 }
 public SerializableModuleData(ModuleData moduleData)
 {
     _moduleData = moduleData;
 }