/// <exception cref="IOException"/> /// <exception cref="BadImageFormatException" /> private AssemblyMetadata CreateAssemblyMetadata( FileKey fileKey, ModuleMetadata manifestModule, List <ITemporaryStreamStorage> storages, Func <FileKey, List <ITemporaryStreamStorage>, ModuleMetadata> moduleMetadataFactory) { var moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance(); string assemblyDir = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder.Count == 0) { moduleBuilder.Add(manifestModule); assemblyDir = Path.GetDirectoryName(fileKey.FullPath); } var moduleFileKey = FileKey.Create(PathUtilities.CombineAbsoluteAndRelativePaths(assemblyDir, moduleName)); var metadata = moduleMetadataFactory(moduleFileKey, storages); moduleBuilder.Add(metadata); } if (moduleBuilder.Count == 0) { moduleBuilder.Add(manifestModule); } return(AssemblyMetadata.Create( moduleBuilder.ToImmutableAndFree())); }
/// <exception cref="IOException"/> /// <exception cref="BadImageFormatException" /> private AssemblyMetadata CreateAssemblyMetadata( FileKey fileKey, ModuleMetadata manifestModule, List <ITemporaryStreamStorage> storages, Func <FileKey, List <ITemporaryStreamStorage>, ModuleMetadata> moduleMetadataGetter) { ImmutableArray <ModuleMetadata> .Builder moduleBuilder = null; string assemblyDir = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder == null) { moduleBuilder = ImmutableArray.CreateBuilder <ModuleMetadata>(); moduleBuilder.Add(manifestModule); assemblyDir = Path.GetDirectoryName(fileKey.FullPath); } var moduleFileKey = FileKey.Create(PathUtilities.CombineAbsoluteAndRelativePaths(assemblyDir, moduleName)); var metadata = moduleMetadataGetter(moduleFileKey, storages); moduleBuilder.Add(metadata); } var modules = (moduleBuilder != null) ? moduleBuilder.ToImmutable() : ImmutableArray.Create(manifestModule); return(AssemblyMetadata.Create(modules)); }
private MetadataShadowCopy GetMetadataShadowCopyNoCheck( string fullPath, MetadataImageKind kind ) { if (kind < MetadataImageKind.Assembly || kind > MetadataImageKind.Module) { throw new ArgumentOutOfRangeException(nameof(kind)); } FileKey key = FileKey.Create(fullPath); lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { return(existing.Public); } } CacheEntry <MetadataShadowCopy> newCopy = CreateMetadataShadowCopy(fullPath, kind); // last-write timestamp is copied from the original file at the time the snapshot was made: bool fault = true; try { key = new FileKey( fullPath, FileUtilities.GetFileTimeStamp(newCopy.Public.PrimaryModule.FullPath) ); fault = false; } finally { if (fault) { newCopy.Private.Dispose(); } } lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { newCopy.Private.Dispose(); return(existing.Public); } _shadowCopies.Add(key, newCopy); } return(newCopy.Public); }
/// <summary> /// A unique file key encapsulates a file path, and change date /// that can be used as the key to a dictionary. /// If a file hasn't changed name or timestamp, we assume /// it is unchanged. /// /// Returns null if the file doesn't exist or otherwise can't be accessed. /// </summary> private FileKey?GetUniqueFileKey(string filePath) { try { return(FileKey.Create(filePath)); } catch (Exception) { // There are several exceptions that can occur here: NotSupportedException or PathTooLongException // for a bad path, UnauthorizedAccessException for access denied, etc. Rather than listing them all, // just catch all exceptions. return(null); } }
/// <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); } }