private AssemblyMetadata CreateAssemblyMetadata(FileStream manifestModuleCopyStream, string originalPath, string shadowCopyPath) { // We don't need to use the global metadata cache here since the shadow copy // won't change and is private to us - only users of the same shadow copy provider see it. ImmutableArray <ModuleMetadata> .Builder moduleBuilder = null; bool fault = true; ModuleMetadata manifestModule = null; try { manifestModule = CreateModuleMetadata(manifestModuleCopyStream); string originalDirectory = null, shadowCopyDirectory = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder == null) { moduleBuilder = ImmutableArray.CreateBuilder <ModuleMetadata>(); moduleBuilder.Add(manifestModule); originalDirectory = Path.GetDirectoryName(originalPath); shadowCopyDirectory = Path.GetDirectoryName(shadowCopyPath); } FileStream moduleCopyStream = CopyFile( originalPath: Path.Combine(originalDirectory, moduleName), shadowCopyPath: Path.Combine(shadowCopyDirectory, moduleName)); moduleBuilder.Add(CreateModuleMetadata(moduleCopyStream)); } var modules = (moduleBuilder != null) ? moduleBuilder.ToImmutable() : ImmutableArray.Create(manifestModule); fault = false; return(AssemblyMetadata.Create(modules)); } finally { if (fault) { if (manifestModule != null) { manifestModule.Dispose(); } if (moduleBuilder != null) { for (int i = 1; i < moduleBuilder.Count; i++) { moduleBuilder[i].Dispose(); } } } } }
public MetadataReference CreateReference(ImmutableArray <string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider) { if (this.IsEmpty) { return(null); } // first see whether we can use native memory directly. var stream = _storage.ReadStream(); var supportNativeMemory = stream as ISupportDirectMemoryAccess; if (supportNativeMemory != null) { // this is unfortunate that if we give stream, compiler will just re-copy whole content to // native memory again. this is a way to get around the issue by we getting native memory ourselves and then // give them pointer to the native memory. also we need to handle lifetime ourselves. var metadata = AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length)); var referenceWithNativeMemory = metadata.GetReference( documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: _assemblyName); // tie lifetime of stream to metadata reference we created. native memory's lifetime is tied to // stream internally and stream is shared between same temporary storage. so here, we should be // sharing same native memory for all skeleton assemblies from same project snapshot. s_lifetime.GetValue(referenceWithNativeMemory, _ => stream); return(referenceWithNativeMemory); } // Otherwise, we just let it use stream. Unfortunately, if we give stream, compiler will // internally copy it to native memory again. since compiler owns lifetime of stream, // it would be great if compiler can be little bit smarter on how it deals with stream. // We don't deterministically release the resulting metadata since we don't know // when we should. So we leave it up to the GC to collect it and release all the associated resources. var metadataFromStream = AssemblyMetadata.CreateFromStream(stream); return(metadataFromStream.GetReference( documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: _assemblyName)); }
public MetadataReference CreateReference(ImmutableArray <string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider) { if (this.IsEmpty) { return(null); } // first see whether we can use native memory directly. var stream = _storage.ReadStream(); var supportNativeMemory = stream as ISupportDirectMemoryAccess; AssemblyMetadata metadata; if (supportNativeMemory != null) { // this is unfortunate that if we give stream, compiler will just re-copy whole content to // native memory again. this is a way to get around the issue by we getting native memory ourselves and then // give them pointer to the native memory. also we need to handle lifetime ourselves. metadata = AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length)); // Tie lifetime of stream to metadata we created. It is important to tie this to the Metadata and not the // metadata reference, as PE symbols hold onto just the Metadata. We can use Add here since we created // a brand new object in AssemblyMetadata.Create above. s_lifetime.Add(metadata, supportNativeMemory); } else { // Otherwise, we just let it use stream. Unfortunately, if we give stream, compiler will // internally copy it to native memory again. since compiler owns lifetime of stream, // it would be great if compiler can be little bit smarter on how it deals with stream. // We don't deterministically release the resulting metadata since we don't know // when we should. So we leave it up to the GC to collect it and release all the associated resources. metadata = AssemblyMetadata.CreateFromStream(stream); } return(metadata.GetReference( documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: _assemblyName)); }
public MetadataReference CreateReference(string alias, bool embedInteropTypes, DocumentationProvider documentationProvider) { if (this.IsEmpty) { return(null); } // first see whether we can use native memory directly. var stream = this.storage.ReadStream(); var supportNativeMemory = stream as ISupportDirectMemoryAccess; if (supportNativeMemory != null) { // this is unfortunate that if we give stream, compiler will just re-copy whole content to // native memory again. this is a way to get around the issue by we getting native memory ourselves and then // give them pointer to the native memory. also we need to handle lifetime ourselves. var referenceWithNativeMemory = new MetadataImageReference( AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length)), documentation: documentationProvider, alias: alias, embedInteropTypes: embedInteropTypes, display: this.assemblyName); // tie lifetime of stream to metadata reference we created. native memory's lifetime is tied to // stream internally and stream is shared between same temporary storage. so here, we should be // sharing same native memory for all skeleton assemblies from same project snapshot. lifetime.GetValue(referenceWithNativeMemory, _ => stream); return(referenceWithNativeMemory); } // otherwise, we just let it use stream. unfortunately, if we give stream, compiler will // internally copy it to native memory again. since compiler owns lifetime of stream, // it would be great if compiler can be little bit smarter on how it deals with stream. return(new MetadataImageReference( stream, documentation: documentationProvider, alias: alias, embedInteropTypes: embedInteropTypes, display: this.assemblyName)); }