internal CoreTypes(MetadataLoadContext loader, string coreAssemblyName) { int numCoreTypes = (int)CoreType.NumCoreTypes; RoType[] coreTypes = new RoType[numCoreTypes]; Exception[] exceptions = new Exception[numCoreTypes]; RoAssembly coreAssembly = loader.TryGetCoreAssembly(coreAssemblyName, out Exception e); if (coreAssembly == null) { // If the core assembly was not found, don't continue. throw e; } else { for (int i = 0; i < numCoreTypes; i++) { ((CoreType)i).GetFullName(out byte[] ns, out byte[] name); RoType type = coreAssembly.GetTypeCore(ns, name, ignoreCase: false, out e); coreTypes[i] = type; if (type == null) { exceptions[i] = e; } } } _coreTypes = coreTypes; _exceptions = exceptions; }
internal RoAssembly ResolveAssembly(RoAssemblyName refName) { Debug.Assert(refName != null); RoAssembly assembly = TryResolveAssembly(refName, out Exception e); return(assembly ?? throw e); }
private RoAssembly LoadFromStreamCore(Stream peStream) { PEReader peReader = new PEReader(peStream); PEReader peReaderToDispose = peReader; // Ensure peReader is disposed immediately if we throw an exception before we're done. try { if (!peReader.HasMetadata) { throw new BadImageFormatException(SR.NoMetadataInPeImage); } string location = (peStream is FileStream fs) ? (fs.Name ?? string.Empty) : string.Empty; MetadataReader reader = peReader.GetMetadataReader(); RoAssembly candidate = new EcmaAssembly(this, peReader, reader, location); AssemblyNameData defNameData = candidate.GetAssemblyNameDataNoCopy(); byte[] pkt = defNameData.PublicKeyToken ?? Array.Empty <byte>(); if (pkt.Length == 0 && defNameData.PublicKey != null && defNameData.PublicKey.Length != 0) { pkt = defNameData.PublicKey.ComputePublicKeyToken(); } RoAssemblyName defName = new RoAssemblyName(defNameData.Name, defNameData.Version, defNameData.CultureName, pkt); RoAssembly winner = _loadedAssemblies.GetOrAdd(defName, candidate); if (winner == candidate) { // We won the race. RegisterForDisposal(peReader); peReaderToDispose = null; return(_binds.GetOrAdd(defName, winner)); // What if we lost the race to bind the defName in the _binds list? Should we ignore it and return the newly created assembly // (like Assembly.LoadModule()) does or return the prior assembly (like we do if we lose the race to commit into _loadedAssemblies?) // There's no perfect answer here. Fundamentally, the dilemma comes about because our apis don't lets apps properly separate // the act of creating an Assembly object from the act of committing the MetadataLoadContext to bind to it. // // We will choose to return the prior winner so that the api is consistent with itself. This is how other LoadFrom() // apis work and they're used a lot more than LoadModule(). } else { // We lost the race but check for a Mvid mismatch. if (candidate.ManifestModule.ModuleVersionId != winner.ManifestModule.ModuleVersionId) { throw new FileLoadException(SR.Format(SR.FileLoadDuplicateAssemblies, defName)); } } return(winner); } finally { peReaderToDispose?.Dispose(); } }
private RoAssembly LoadFromStreamCore(Stream peStream) { PEReader peReader = new PEReader(peStream); PEReader?peReaderToDispose = peReader; // Ensure peReader is disposed immediately if we throw an exception before we're done. try { if (!peReader.HasMetadata) { throw new BadImageFormatException(SR.NoMetadataInPeImage); } string location = (peStream is FileStream fs) ? (fs.Name ?? string.Empty) : string.Empty; MetadataReader reader = peReader.GetMetadataReader(); RoAssembly candidate = new EcmaAssembly(this, peReader, reader, location); AssemblyNameData defNameData = candidate.GetAssemblyNameDataNoCopy(); byte[] pkt = defNameData.PublicKeyToken ?? Array.Empty <byte>(); if (pkt.Length == 0 && defNameData.PublicKey != null && defNameData.PublicKey.Length != 0) { pkt = defNameData.PublicKey.ComputePublicKeyToken() !; } RoAssemblyName defName = new RoAssemblyName(defNameData.Name, defNameData.Version, defNameData.CultureName, pkt, defNameData.Flags); RoAssembly winner = _loadedAssemblies.GetOrAdd(defName, candidate); if (winner == candidate) { // We won the race. RegisterForDisposal(peReader); peReaderToDispose = null; // We do not add to the _binds list because the binding list is only for assemblies that have been resolved through // the Resolve method. This allows the resolver to have complete control over selecting the appropriate assembly // based on Version, CultureName and PublicKeyToken. return(winner); } else { // We lost the race but check for a Mvid mismatch. if (candidate.ManifestModule.ModuleVersionId != winner.ManifestModule.ModuleVersionId) { throw new FileLoadException(SR.Format(SR.FileLoadDuplicateAssemblies, defName)); } } return(winner); } finally { peReaderToDispose?.Dispose(); } }
private RoAssembly TryGetDefaultCoreAssembly(out Exception e) { foreach (string coreName in s_CoreNames) { RoAssemblyName roAssemblyName = new AssemblyName(coreName).ToRoAssemblyName(); RoAssembly roAssembly = TryResolveAssembly(roAssemblyName, out e); // Stop on the first core assembly we find if (roAssembly != null) { e = null; return(roAssembly); } } e = new FileNotFoundException(SR.UnableToDetermineCoreAssembly); return(null); }