public static CompositionConfiguration Create()

in src/Microsoft.VisualStudio.Composition/CompositionConfiguration.cs [75:203]


        public static CompositionConfiguration Create(ComposableCatalog catalog)
        {
            Requires.NotNull(catalog, nameof(catalog));

            // We consider all the parts in the catalog, plus the specially synthesized ones
            // that should always be applied.
            var customizedCatalog = catalog.AddParts(AlwaysBundledParts);

            // Construct our part builders, initialized with all their imports satisfied.
            // We explicitly use reference equality because ComposablePartDefinition.Equals is too slow, and unnecessary for this.
            var partBuilders = new Dictionary<ComposablePartDefinition, PartBuilder>(ReferenceEquality<ComposablePartDefinition>.Default);
            foreach (ComposablePartDefinition partDefinition in customizedCatalog.Parts)
            {
                var satisfyingImports = partDefinition.Imports.ToImmutableDictionary(i => i, i => customizedCatalog.GetExports(i.ImportDefinition));
                partBuilders.Add(partDefinition, new PartBuilder(partDefinition, satisfyingImports));
            }

            // Create a lookup table that gets all immediate importers for each part.
            foreach (PartBuilder partBuilder in partBuilders.Values)
            {
                // We want to understand who imports each part so we can properly propagate sharing boundaries
                // for MEFv1 attributed parts. ExportFactory's that create sharing boundaries are an exception
                // because if a part has a factory that creates new sharing boundaries, the requirement for
                // that sharing boundary of the child scope shouldn't be interpreted as a requirement for that
                // same boundary by the parent part.
                // However, if the ExportFactory does not create sharing boundaries, it does in fact need all
                // the same sharing boundaries as the parts it constructs.
                var importedPartsExcludingFactoriesWithSharingBoundaries =
                    (from entry in partBuilder.SatisfyingExports
                     where !entry.Key.IsExportFactory || entry.Key.ImportDefinition.ExportFactorySharingBoundaries.Count == 0
                     from export in entry.Value
                     select export.PartDefinition).Distinct(ReferenceEquality<ComposablePartDefinition>.Default);
                foreach (var importedPartDefinition in importedPartsExcludingFactoriesWithSharingBoundaries)
                {
                    var importedPartBuilder = partBuilders[importedPartDefinition];
                    importedPartBuilder.ReportImportingPart(partBuilder);
                }
            }

            // Propagate sharing boundaries defined on parts to all importers (transitive closure).
            foreach (PartBuilder partBuilder in partBuilders.Values)
            {
                partBuilder.ApplySharingBoundary();
            }

            var sharingBoundaryOverrides = ComputeInferredSharingBoundaries(partBuilders.Values);

            // Build up our set of composed parts.
            var partsBuilder = ImmutableHashSet.CreateBuilder<ComposedPart>();
            foreach (var partBuilder in partBuilders.Values)
            {
                var composedPart = new ComposedPart(partBuilder.PartDefinition, partBuilder.SatisfyingExports, partBuilder.RequiredSharingBoundaries.ToImmutableHashSet());
                partsBuilder.Add(composedPart);
            }

            var parts = partsBuilder.ToImmutable();

            // Determine which metadata views to use for each applicable import.
            var metadataViewsAndProviders = GetMetadataViewProvidersMap(customizedCatalog);

            // Validate configuration.
            var errors = new List<ComposedPartDiagnostic>();
            foreach (var part in parts)
            {
                errors.AddRange(part.Validate(metadataViewsAndProviders));
            }

            // Detect loops of all non-shared parts.
            errors.AddRange(FindLoops(parts));

            // If errors are found, re-validate the salvaged parts in case there are parts whose dependencies are affected by the initial errors
            if (errors.Count > 0)
            {
                // Set salvaged parts to current catalog in case there are no errors
                var salvagedParts = parts;
                var salvagedPartDefinitions = catalog.Parts;

                List<ComposedPartDiagnostic> previousErrors = errors;
                Stack<IReadOnlyCollection<ComposedPartDiagnostic>> stackedErrors = new Stack<IReadOnlyCollection<ComposedPartDiagnostic>>();

                // While we still find errors we validate the exports so that we remove all dependency failures
                while (previousErrors.Count > 0)
                {
                    stackedErrors.Push(previousErrors);

                    // Get the salvaged parts
                    var invalidParts = previousErrors.SelectMany(error => error.Parts).ToList();

                    if (invalidParts.Count == 0)
                    {
                        // If we can't identify the faulty parts but we still have errors, we have to just throw.
                        throw new CompositionFailedException(Strings.FailStableComposition, ImmutableStack.Create<IReadOnlyCollection<ComposedPartDiagnostic>>(errors));
                    }

                    salvagedParts = salvagedParts.Except(invalidParts);
                    var invalidPartDefinitionsSet = new HashSet<ComposablePartDefinition>(invalidParts.Select(p => p.Definition));
                    salvagedPartDefinitions = salvagedPartDefinitions.Except(invalidPartDefinitionsSet);

                    // Empty the list so that we create a new one only with the new set of errors
                    previousErrors = new List<ComposedPartDiagnostic>();

                    foreach (var part in salvagedParts)
                    {
                        previousErrors.AddRange(part.RemoveSatisfyingExports(invalidPartDefinitionsSet));
                    }
                }

                var finalCatalog = ComposableCatalog.Create(catalog.Resolver).AddParts(salvagedPartDefinitions);

                // We want the first found errors to come out of the stack first, so we need to invert the current stack.
                var compositionErrors = ImmutableStack.CreateRange(stackedErrors);

                var configuration = new CompositionConfiguration(
                    finalCatalog,
                    salvagedParts,
                    metadataViewsAndProviders,
                    compositionErrors,
                    sharingBoundaryOverrides);

                return configuration;
            }

            return new CompositionConfiguration(
                catalog,
                parts,
                metadataViewsAndProviders,
                ImmutableStack<IReadOnlyCollection<ComposedPartDiagnostic>>.Empty,
                sharingBoundaryOverrides);
        }