Beispiel #1
0
        internal static PortableExecutableReference CreateFromFile(
            Stream peStream,
            string path,
            MetadataReferenceProperties properties = default,
            DocumentationProvider?documentation    = null
            )
        {
            // prefetch image, close stream to avoid locking it:
            var module = ModuleMetadata.CreateFromStream(
                peStream,
                PEStreamOptions.PrefetchEntireImage
                );

            if (properties.Kind == MetadataImageKind.Module)
            {
                return(new MetadataImageReference(
                           module,
                           properties,
                           documentation,
                           path,
                           display: null
                           ));
            }

            // any additional modules constituting the assembly will be read lazily:
            var assemblyMetadata = AssemblyMetadata.CreateFromFile(module, path);

            return(new MetadataImageReference(
                       assemblyMetadata,
                       properties,
                       documentation,
                       path,
                       display: null
                       ));
        }
Beispiel #2
0
        /// <summary>
        /// Gets or creates metadata for specified file path.
        /// </summary>
        /// <param name="fullPath">Full path to an assembly manifest module file or a standalone module file.</param>
        /// <param name="kind">Metadata kind (assembly or module).</param>
        /// <returns>Metadata for the specified file.</returns>
        /// <exception cref="IOException">Error reading file <paramref name="fullPath"/>. See <see cref="Exception.InnerException"/> for details.</exception>
        public Metadata GetMetadata(string fullPath, MetadataImageKind kind)
        {
            if (NeedsShadowCopy(fullPath))
            {
                return(GetMetadataShadowCopyNoCheck(fullPath, kind).Metadata);
            }

            FileKey key = FileKey.Create(fullPath);

            lock (Guard)
            {
                CacheEntry <Metadata> existing;
                if (_noShadowCopyCache.TryGetValue(key, out existing))
                {
                    return(existing.Public);
                }
            }

            Metadata newMetadata;

            if (kind == MetadataImageKind.Assembly)
            {
                newMetadata = AssemblyMetadata.CreateFromFile(fullPath);
            }
            else
            {
                newMetadata = ModuleMetadata.CreateFromFile(fullPath);
            }

            // the files are locked (memory mapped) now
            key = FileKey.Create(fullPath);

            lock (Guard)
            {
                CacheEntry <Metadata> existing;
                if (_noShadowCopyCache.TryGetValue(key, out existing))
                {
                    newMetadata.Dispose();
                    return(existing.Public);
                }

                Metadata publicMetadata = newMetadata.Copy();
                _noShadowCopyCache.Add(key, new CacheEntry <Metadata>(publicMetadata, newMetadata));
                return(publicMetadata);
            }
        }
        /// <exception cref="IOException"/>
        private static AssemblyMetadata GetOrCreateAssemblyFromFile(string fullPath)
        {
            AssemblyMetadata assembly = null;

            // may throw:
            FileKey key = FileKey.Create(fullPath);

            CachedAssembly cachedAssembly;
            bool           existingKey = assembliesFromFiles.TryGetValue(key, out cachedAssembly);

            if (existingKey && cachedAssembly.Metadata.TryGetTarget(out assembly))
            {
                return(assembly);
            }

            // memory-map all modules of the assembly:
            assembly = AssemblyMetadata.CreateFromFile(fullPath);

            // refresh the timestamp (the file may have changed just before we memory-mapped it):
            bool fault = true;

            try
            {
                key   = FileKey.Create(fullPath);
                fault = false;
            }
            finally
            {
                if (fault)
                {
                    assembly.Dispose();
                }
            }

            cachedAssembly           = new CachedAssembly(assembly);
            assembliesFromFiles[key] = cachedAssembly;

            if (!existingKey)
            {
                assemblyKeys.Add(key);
                EnableCompactTimer();
            }

            return(assembly);
        }
Beispiel #4
0
        /// <summary>
        /// Creates a reference to an assembly or standalone module stored in a file.
        /// Reads the content of the file into memory.
        /// </summary>
        /// <param name="path">Path to the assembly file.</param>
        /// <param name="properties">Reference properties (extern aliases, type embedding, <see cref="MetadataImageKind"/>).</param>
        /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="path"/> is invalid.</exception>
        /// <exception cref="IOException">An error occurred while reading the file.</exception>
        /// <remarks>
        /// Performance considerations:
        /// <para>
        /// It is recommended to use <see cref="AssemblyMetadata.CreateFromFile(string)"/> or <see cref="ModuleMetadata.CreateFromFile(string)"/>
        /// API when creating multiple references to the same file.
        /// Reusing <see cref="Metadata"/> object allows for sharing data across these references.
        /// </para>
        /// <para>
        /// The method eagerly reads the entire content of the file into native heap. The native memory block is released
        /// when the resulting reference becomes unreachable and GC collects it. To decrease memory footprint of the reference and/or manage
        /// the lifetime deterministically use <see cref="AssemblyMetadata.CreateFromFile(string)"/>
        /// to create an <see cref="IDisposable"/> metadata object and
        /// <see cref="AssemblyMetadata.GetReference(DocumentationProvider, ImmutableArray{string}, bool, string, string)"/>
        /// to get a reference to it.
        /// </para>
        /// </remarks>
        public static PortableExecutableReference CreateFromFile(
            string path,
            MetadataReferenceProperties properties = default(MetadataReferenceProperties),
            DocumentationProvider documentation    = null)
        {
            var peStream = FileUtilities.OpenFileStream(path);

            // prefetch image, close stream to avoid locking it:
            var module = ModuleMetadata.CreateFromStream(peStream, PEStreamOptions.PrefetchEntireImage);

            if (properties.Kind == MetadataImageKind.Module)
            {
                return(module.GetReference(documentation, path));
            }

            // any additional modules constituting the assembly will be read lazily:
            var assemblyMetadata = AssemblyMetadata.CreateFromFile(module, path);

            return(assemblyMetadata.GetReference(documentation, properties.Aliases, properties.EmbedInteropTypes, path));
        }