/// <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()); }
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; }
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(); } })); }
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)); }