Example #1
0
        private static RuntimeImport CreateRuntimeImport(ImportDefinitionBinding importDefinitionBinding, IReadOnlyList <ExportDefinitionBinding> satisfyingExports, Resolver resolver)
        {
            Requires.NotNull(importDefinitionBinding, nameof(importDefinitionBinding));
            Requires.NotNull(satisfyingExports, nameof(satisfyingExports));

            var runtimeExports = satisfyingExports.Select(export => CreateRuntimeExport(export, resolver)).ToImmutableArray();

            if (importDefinitionBinding.ImportingMemberRef != null)
            {
                return(new RuntimeImport(
                           importDefinitionBinding.ImportingMemberRef,
                           importDefinitionBinding.ImportingSiteTypeRef,
                           importDefinitionBinding.ImportingSiteTypeWithoutCollectionRef,
                           importDefinitionBinding.ImportDefinition.Cardinality,
                           runtimeExports,
                           PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinitionBinding.ImportDefinition),
                           importDefinitionBinding.IsExportFactory,
                           importDefinitionBinding.ImportDefinition.Metadata,
                           importDefinitionBinding.ImportDefinition.ExportFactorySharingBoundaries));
            }
            else
            {
                return(new RuntimeImport(
                           importDefinitionBinding.ImportingParameterRef,
                           importDefinitionBinding.ImportingSiteTypeRef,
                           importDefinitionBinding.ImportingSiteTypeWithoutCollectionRef,
                           importDefinitionBinding.ImportDefinition.Cardinality,
                           runtimeExports,
                           PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinitionBinding.ImportDefinition),
                           importDefinitionBinding.IsExportFactory,
                           importDefinitionBinding.ImportDefinition.Metadata,
                           importDefinitionBinding.ImportDefinition.ExportFactorySharingBoundaries));
            }
        }
            private protected override IEnumerable <ExportInfo> GetExportsCore(ImportDefinition importDefinition)
            {
                var exports = this.composition.GetExports(importDefinition.ContractName);

                return
                    (from export in exports
                     let part = this.composition.GetPart(export)
                                select this.CreateExport(
                         importDefinition,
                         export.Metadata,
                         part.TypeRef,
                         GetPartConstructedTypeRef(part, importDefinition.Metadata),
                         part.SharingBoundary,
                         !part.IsShared || PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinition),
                         export.MemberRef));
            }
        private static IEnumerable <ComposedPartDiagnostic> FindLoops(IEnumerable <ComposedPart> parts)
        {
            Requires.NotNull(parts, nameof(parts));

            var partByPartDefinition  = parts.ToDictionary(p => p.Definition);
            var partByPartType        = parts.ToDictionary(p => p.Definition.TypeRef);
            var partsAndDirectImports = new Dictionary <ComposedPart, IReadOnlyList <KeyValuePair <ImportDefinitionBinding, ComposedPart> > >();

            foreach (var part in parts)
            {
                var directlyImportedParts = (from importAndExports in part.SatisfyingExports
                                             from export in importAndExports.Value
                                             let exportingPart = partByPartDefinition[export.PartDefinition]
                                                                 select new KeyValuePair <ImportDefinitionBinding, ComposedPart>(importAndExports.Key, exportingPart)).ToList();
                partsAndDirectImports.Add(part, directlyImportedParts);
            }

            Func <Func <KeyValuePair <ImportDefinitionBinding, ComposedPart>, bool>, Func <ComposedPart, IEnumerable <ComposedPart> > > getDirectLinksWithFilter =
                filter => (part => partsAndDirectImports[part].Where(filter).Select(ip => ip.Value));
            var visited = new HashSet <ComposedPart>();

            // Find any loops of exclusively non-shared parts.
            var nonSharedPartsInLoops = new HashSet <ComposedPart>();

            foreach (var part in partsAndDirectImports.Keys)
            {
                if (nonSharedPartsInLoops.Contains(part))
                {
                    // Don't check and report parts already detected to be involved in a loop.
                    continue;
                }

                visited.Clear();
                var path = PathExistsBetween(part, part, getDirectLinksWithFilter(ip => !ip.Key.IsExportFactory && (!ip.Value.Definition.IsShared || PartCreationPolicyConstraint.IsNonSharedInstanceRequired(ip.Key.ImportDefinition))), visited);
                if (!path.IsEmpty)
                {
                    path = path.Push(part);
                    nonSharedPartsInLoops.UnionWith(path);
                    yield return(new ComposedPartDiagnostic(path, Strings.LoopBetweenNonSharedParts));
                }
            }

            // Find loops even with shared parts where an importing constructor is involved.
            Func <KeyValuePair <ImportDefinitionBinding, ComposedPart>, bool> importingConstructorFilter = ip => !ip.Key.IsExportFactory && !ip.Key.IsLazy;

            foreach (var partAndImports in partsAndDirectImports)
            {
                var importingPart = partAndImports.Key;
                foreach (var import in partAndImports.Value)
                {
                    var importDefinitionBinding = import.Key;
                    var satisfyingPart          = import.Value;
                    if (importDefinitionBinding.ImportingParameterRef != null && importingConstructorFilter(import))
                    {
                        visited.Clear();
                        var path = PathExistsBetween(satisfyingPart, importingPart, getDirectLinksWithFilter(importingConstructorFilter), visited);
                        if (!path.IsEmpty)
                        {
                            path = path.Push(satisfyingPart).Push(partByPartType[importDefinitionBinding.ComposablePartTypeRef]);
                            yield return(new ComposedPartDiagnostic(path, Strings.LoopInvolvingImportingCtorArgumentAndAllNonLazyImports));
                        }
                    }
                }
            }
        }