Exemple #1
0
        /// <summary>
        /// Creates a catalog that exports an instance of <see cref="MefV1.ICompositionService"/>.
        /// </summary>
        /// <param name="catalog">The catalog to add the export to.</param>
        /// <returns>A catalog that includes <see cref="MefV1.ICompositionService"/>.</returns>
        public static ComposableCatalog WithCompositionService(this ComposableCatalog catalog)
        {
            Requires.NotNull(catalog, nameof(catalog));

            var modifiedCatalog = catalog.AddPart(CompositionServicePart);

            return(modifiedCatalog);
        }
        /// <summary>
        /// Adds parts that allow MEF to work on .NET Framework platforms.
        /// </summary>
        /// <param name="catalog">The catalog to add desktop support to.</param>
        /// <returns>The catalog that includes desktop support.</returns>
        public static ComposableCatalog WithDesktopSupport(this ComposableCatalog catalog)
        {
            Requires.NotNull(catalog, nameof(catalog));

            return(catalog
                   .AddPart(MetadataViewImplProxyPart)
                   .WithMetadataViewEmitProxySupport());
        }
Exemple #3
0
 internal ComposableCatalog ReadComposableCatalog()
 {
     using (this.Trace(nameof(ComposableCatalog)))
     {
         var parts = this.ReadList(this.ReadComposablePartDefinition);
         return(ComposableCatalog.Create(this.Resolver).AddParts(parts));
     }
 }
        private CompositionConfiguration(ComposableCatalog catalog, ISet <ComposedPart> parts, IReadOnlyDictionary <Type, ExportDefinitionBinding> metadataViewsAndProviders, IImmutableStack <IReadOnlyCollection <ComposedPartDiagnostic> > compositionErrors, ImmutableDictionary <ComposablePartDefinition, string> effectiveSharingBoundaryOverrides)
        {
            Requires.NotNull(catalog, nameof(catalog));
            Requires.NotNull(parts, nameof(parts));
            Requires.NotNull(metadataViewsAndProviders, nameof(metadataViewsAndProviders));
            Requires.NotNull(compositionErrors, nameof(compositionErrors));
            Requires.NotNull(effectiveSharingBoundaryOverrides, nameof(effectiveSharingBoundaryOverrides));

            this.Catalog = catalog;
            this.Parts   = parts;
            this.MetadataViewsAndProviders         = metadataViewsAndProviders;
            this.CompositionErrors                 = compositionErrors;
            this.effectiveSharingBoundaryOverrides = effectiveSharingBoundaryOverrides;
        }
Exemple #5
0
        public Task SaveAsync(ComposableCatalog catalog, Stream cacheStream, CancellationToken cancellationToken = default(CancellationToken))
        {
            Requires.NotNull(catalog, nameof(catalog));
            Requires.NotNull(cacheStream, nameof(cacheStream));

            return(Task.Run(() =>
            {
                using (var writer = new BinaryWriter(cacheStream, TextEncoding, leaveOpen: true))
                {
                    var context = new SerializationContext(writer, catalog.Parts.Count * 4, catalog.Resolver);
                    context.Write(catalog);
                    context.FinalizeObjectTableCapacity();
                }
            }));
        }
Exemple #6
0
 public static ComposableCatalog WithDesktopSupport(this ComposableCatalog catalog)
 {
     Requires.NotNull(catalog, nameof(catalog));
     return(catalog);
 }
        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));
        }
        private static ImmutableDictionary <Type, ExportDefinitionBinding> GetMetadataViewProvidersMap(ComposableCatalog customizedCatalog)
        {
            Requires.NotNull(customizedCatalog, nameof(customizedCatalog));

            var providers = (
                from part in customizedCatalog.Parts
                from export in part.ExportDefinitions
                where export.Value.ContractName == ContractNameServices.GetTypeIdentity(typeof(IMetadataViewProvider))
                orderby ExportProvider.GetOrderMetadata(export.Value.Metadata) descending
                let exportDefinitionBinding = new ExportDefinitionBinding(export.Value, part, default(MemberRef))
                                              let provider = (IMetadataViewProvider)part.ImportingConstructorOrFactory !.Instantiate(Type.EmptyTypes)
                                                             select Tuple.Create(provider, exportDefinitionBinding)).ToList();

            var metadataTypes = new HashSet <Type>(
                from part in customizedCatalog.Parts
                from import in part.Imports
                where import.MetadataType != null
                select import.MetadataType);

            // Make sure that a couple of "primitive" metadata types are included.
            metadataTypes.Add(typeof(IDictionary <string, object>));
            metadataTypes.Add(typeof(IReadOnlyDictionary <string, object>));

            // Find metadata view providers for each metadata type.
            // Don't worry about the ones we can't find. Part validation happens later
            // and they will notice when metadata view providers aren't available and create errors at that time.
            var metadataViewsAndProviders = ImmutableDictionary.CreateBuilder <Type, ExportDefinitionBinding>();

            foreach (var metadataType in metadataTypes)
            {
                var provider = providers.FirstOrDefault(p => p.Item1.IsMetadataViewSupported(metadataType));
                if (provider != null)
                {
                    metadataViewsAndProviders.Add(metadataType, provider.Item2);
                }
            }

            return(metadataViewsAndProviders.ToImmutable());
        }
 private V3(MEFv3.ComposableCatalog catalog)
 {
     this.catalog = catalog;
 }
        /// <summary>
        /// Adds support for queries to <see cref="ExportProvider.GetExports{T, TMetadata}()"/> where
        /// <c>TMetadata</c> is an interface.
        /// </summary>
        /// <param name="catalog">The catalog from which constructed ExportProviders may have this support added.</param>
        /// <returns>The catalog with the additional support.</returns>
        public static ComposableCatalog WithMetadataViewEmitProxySupport(this ComposableCatalog catalog)
        {
            Requires.NotNull(catalog, nameof(catalog));

            return(catalog.AddPart(ProxySupportPartDefinition));
        }