Esempio n. 1
0
        /// <summary>
        /// Gets a <see cref="MetadataReader"/> from a <see cref="MetadataReaderProvider"/>.
        /// </summary>
        /// <remarks>
        /// The caller must keep the <see cref="MetadataReaderProvider"/> undisposed throughout the lifetime of the metadata reader.
        ///
        /// If this method is called multiple times each call with arguments equal to the arguments passed to the previous successful call
        /// returns the same instance of <see cref="MetadataReader"/> as the previous call.
        /// </remarks>
        /// <exception cref="ArgumentException">The encoding of <paramref name="utf8Decoder"/> is not <see cref="UTF8Encoding"/>.</exception>
        /// <exception cref="PlatformNotSupportedException">The current platform is big-endian.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        /// <exception cref="ObjectDisposedException">Provider has been disposed.</exception>
        public unsafe MetadataReader GetMetadataReader(MetadataReaderOptions options = MetadataReaderOptions.Default, MetadataStringDecoder utf8Decoder = null)
        {
            var cachedReader = _lazyMetadataReader;

            if (CanReuseReader(cachedReader, options, utf8Decoder))
            {
                return(cachedReader);
            }

            // If multiple threads attempt to open a metadata reader with the same options and decoder
            // it's cheaper to wait for the other thread to finish initializing the reader than to open
            // two readers and discard one.
            // Note that it's rare to reader the same metadata using different options.
            lock (_metadataReaderGuard)
            {
                cachedReader = _lazyMetadataReader;

                if (CanReuseReader(cachedReader, options, utf8Decoder))
                {
                    return(cachedReader);
                }

                AbstractMemoryBlock metadata = GetMetadataBlock();
                var newReader = new MetadataReader(metadata.Pointer, metadata.Size, options, utf8Decoder, memoryOwner: this);
                _lazyMetadataReader = newReader;
                return(newReader);
            }
        }
Esempio n. 2
0
 private static bool CanReuseReader(MetadataReader reader, MetadataReaderOptions options, MetadataStringDecoder utf8DecoderOpt)
 {
     return(reader != null && reader.Options == options && ReferenceEquals(reader.UTF8Decoder, utf8DecoderOpt ?? MetadataStringDecoder.DefaultUTF8));
 }
Esempio n. 3
0
        /// <summary>
        /// Gets a <see cref="MetadataReader"/> from a <see cref="PEReader"/>.
        /// </summary>
        /// <remarks>
        /// The caller must keep the <see cref="PEReader"/> undisposed throughout the lifetime of the metadata reader.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="peReader"/> is null</exception>
        /// <exception cref="ArgumentException">The encoding of <paramref name="utf8Decoder"/> is not <see cref="UTF8Encoding"/>.</exception>
        /// <exception cref="PlatformNotSupportedException">The current platform is big-endian.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        public static unsafe MetadataReader GetMetadataReader(this PEReader peReader, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
        {
            if (peReader == null)
            {
                throw new ArgumentNullException(nameof(peReader));
            }

            var metadata = peReader.GetMetadata();

            return(new MetadataReader(metadata.Pointer, metadata.Length, options, utf8Decoder, memoryOwner: peReader));
        }