Example #1
0
        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();
                        }
                    }
                }
            }
        }
Example #2
0
        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));
        }
Example #4
0
        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));
        }