/// <summary> /// Returns a map of those MEF parts that are missing explicit sharing boundaries, and the sharing boundary that can be inferred. /// </summary> /// <param name="partBuilders">The part builders to build the map for.</param> /// <returns>A map of those parts with inferred boundaries where the key is the part and the value is its designated sharing boundary.</returns> private static ImmutableDictionary <ComposablePartDefinition, string> ComputeInferredSharingBoundaries(IEnumerable <PartBuilder> partBuilders) { Requires.NotNull(partBuilders, nameof(partBuilders)); var sharingBoundariesAndMetadata = ComputeSharingBoundaryMetadata(partBuilders); var sharingBoundaryOverrides = ImmutableDictionary.CreateBuilder <ComposablePartDefinition, string>(); foreach (PartBuilder partBuilder in partBuilders) { if (partBuilder.PartDefinition.IsSharingBoundaryInferred) { // ALGORITHM selects: the ONE sharing boundary that // * FILTER 1: does not create ANY of the others // * FILTER 2: can reach ALL the others by following UP the sharing boundary export factory chains. var filter = from boundary in partBuilder.RequiredSharingBoundaries let others = partBuilder.RequiredSharingBoundaries.ToImmutableHashSet().Remove(boundary) where !others.Any(other => sharingBoundariesAndMetadata[other].ParentBoundariesUnion.Contains(boundary)) // filter 1 where others.All(other => sharingBoundariesAndMetadata[boundary].ParentBoundariesIntersection.Contains(other)) // filter 2 select boundary; var qualifyingSharingBoundaries = filter.ToList(); if (qualifyingSharingBoundaries.Count == 1) { sharingBoundaryOverrides.Add(partBuilder.PartDefinition, qualifyingSharingBoundaries[0]); } else if (qualifyingSharingBoundaries.Count > 1) { throw new CompositionFailedException( string.Format( CultureInfo.CurrentCulture, Strings.UnableToDeterminePrimarySharingBoundary, ReflectionHelpers.GetTypeName(partBuilder.PartDefinition.Type, false, true, null, null))); } } } return(sharingBoundaryOverrides.ToImmutable()); }
private static XDocument CreateDgml(ISet <ComposedPart> parts) { Requires.NotNull(parts, nameof(parts)); XElement nodes, links; var dgml = Dgml.Create(out nodes, out links, direction: "RightToLeft") .WithStyle( "ExportFactory", new Dictionary <string, string?> { { "StrokeDashArray", "2,2" }, }, "Link") .WithStyle( "VsMEFBuiltIn", new Dictionary <string, string?> { { "Visibility", "Hidden" }, }); foreach (string?sharingBoundary in parts.Select(p => p.Definition.SharingBoundary).Distinct()) { if (!string.IsNullOrEmpty(sharingBoundary)) { nodes.Add(Dgml.Node(sharingBoundary, sharingBoundary, "Expanded")); } } foreach (var part in parts) { var node = Dgml.Node(part.Definition.Id, ReflectionHelpers.GetTypeName(part.Definition.Type, false, true, null, null)); if (!string.IsNullOrEmpty(part.Definition.SharingBoundary)) { node.ContainedBy(part.Definition.SharingBoundary !, dgml); } string[]? partDgmlCategories; if (part.Definition.Metadata.TryGetValue(CompositionConstants.DgmlCategoryPartMetadataName, out partDgmlCategories)) { node = node.WithCategories(partDgmlCategories); } nodes.Add(node); foreach (var import in part.SatisfyingExports.Keys) { foreach (ExportDefinitionBinding export in part.SatisfyingExports[import]) { string?linkLabel = !export.ExportedValueTypeRef.Equals(export.PartDefinition.TypeRef) ? export.ExportedValueType.ToString() : null; var link = Dgml.Link(export.PartDefinition.Id, part.Definition.Id, linkLabel); if (import.IsExportFactory) { link = link.WithCategories("ExportFactory"); } links.Add(link); } } } return(dgml); }
public void ToString(TextWriter writer) { var indentingWriter = IndentingTextWriter.Get(writer); foreach (var requirement in this.Requirements) { indentingWriter.WriteLine("{0} = {1} (required: {2})", requirement.Key, ReflectionHelpers.GetTypeName(requirement.Value.MetadatumValueType, false, true, null, null), requirement.Value.IsMetadataumValueRequired); } }