Example #1
0
        /// <summary>
        /// Remove any modules that are not in the set of referenced modules.
        /// If there are duplicates of referenced modules, potentially differing by
        /// version, one instance of the highest version is kept and others dropped.
        /// </summary>
        /// <remarks>
        /// Binding against this reduced set of modules will not handle certain valid cases
        /// where binding to full set would succeed (e.g.: binding to types outside the
        /// referenced modules). And since duplicates are dropped, this will prevent resolving
        /// ambiguities between two versions of the same assembly by using aliases. Also,
        /// there is no attempt here to follow binding redirects or to use the CLR to determine
        /// which version of an assembly to prefer when there are duplicate assemblies.
        /// </remarks>
        private static void RemoveUnreferencedModules(
            ArrayBuilder<MetadataReference> modules,
            ArrayBuilder<AssemblyIdentity> identities,
            AssemblyIdentityComparer identityComparer,
            ArrayBuilder<AssemblyIdentity> referencedModules)
        {
            Debug.Assert(modules.Count == identities.Count);

            var referencedIndices = PooledHashSet<int>.GetInstance();

            int n = identities.Count;
            int index;
            foreach (var referencedModule in referencedModules)
            {
                index = -1;
                for (int i = 0; i < n; i++)
                {
                    var identity = identities[i];
                    var compareResult = identityComparer.Compare(referencedModule, identity);
                    switch (compareResult)
                    {
                        case AssemblyIdentityComparer.ComparisonResult.NotEquivalent:
                            break;
                        case AssemblyIdentityComparer.ComparisonResult.Equivalent:
                        case AssemblyIdentityComparer.ComparisonResult.EquivalentIgnoringVersion:
                            if ((index < 0) || (identity.Version > identities[index].Version))
                            {
                                index = i;
                            }
                            break;
                        default:
                            throw ExceptionUtilities.UnexpectedValue(compareResult);
                    }
                }
                if (index >= 0)
                {
                    referencedIndices.Add(index);
                }
            }

            Debug.Assert(referencedIndices.Count <= modules.Count);
            Debug.Assert(referencedIndices.Count <= referencedModules.Count);

            index = 0;
            for (int i = 0; i < n; i++)
            {
                if (referencedIndices.Contains(i))
                {
                    modules[index] = modules[i];
                    index++;
                }
            }
            modules.Clip(index);

            referencedIndices.Free();
        }