Exemplo n.º 1
0
        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);
        }