File: Workspace\Solution\SolutionCompilationState.SkeletonReferenceSet.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Host;
 
namespace Microsoft.CodeAnalysis;
 
internal sealed partial class SolutionCompilationState
{
    /// <param name="metadata">
    /// The actual assembly metadata produced from another compilation.
    /// </param>
    /// <param name="documentationProvider">
    /// The documentation provider used to lookup xml docs for any metadata reference we pass out.  See
    /// docs on <see cref="DeferredDocumentationProvider"/> for why this is safe to hold onto despite it
    /// rooting a compilation internally.
    /// </param>
    private sealed class SkeletonReferenceSet(
        AssemblyMetadata metadata,
        ITemporaryStorageStreamHandle storageHandle,
        string? assemblyName,
        DeferredDocumentationProvider documentationProvider)
    {
        /// <summary>
        /// Lock this object while reading/writing from it.  Used so we can return the same reference for the same
        /// properties.  While this is isn't strictly necessary (as the important thing to keep the same is the
        /// AssemblyMetadata), this allows higher layers to see that reference instances are the same which allow
        /// reusing the same higher level objects (for example, the set of references a compilation has).
        /// </summary>
        private readonly Dictionary<MetadataReferenceProperties, PortableExecutableReference> _referenceMap = [];
 
        public ITemporaryStorageStreamHandle StorageHandle => storageHandle;
 
        public PortableExecutableReference GetOrCreateMetadataReference(MetadataReferenceProperties properties)
        {
            lock (_referenceMap)
            {
                if (!_referenceMap.TryGetValue(properties, out var value))
                {
                    value = metadata.GetReference(
                        documentationProvider,
                        aliases: properties.Aliases,
                        embedInteropTypes: properties.EmbedInteropTypes,
                        display: assemblyName);
 
                    _referenceMap.Add(properties, value);
                }
 
                return value;
            }
        }
    }
}