| File: System\ComponentModel\Composition\Hosting\CatalogExportProvider.ScopeManager.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.Composition\src\System.ComponentModel.Composition.csproj (System.ComponentModel.Composition) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.ComponentModel.Composition.Primitives; namespace System.ComponentModel.Composition.Hosting { public partial class CatalogExportProvider { internal sealed class ScopeManager : ExportProvider { private readonly CompositionScopeDefinition _scopeDefinition; private readonly CatalogExportProvider _catalogExportProvider; public ScopeManager(CatalogExportProvider catalogExportProvider, CompositionScopeDefinition scopeDefinition) { ArgumentNullException.ThrowIfNull(catalogExportProvider); ArgumentNullException.ThrowIfNull(scopeDefinition); _scopeDefinition = scopeDefinition; _catalogExportProvider = catalogExportProvider; } protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition? atomicComposition) { List<Export> exports = new List<Export>(); ImportDefinition? queryImport = TranslateImport(definition); if (queryImport == null) { return exports; } // go through the catalogs and see if there's anything there of interest foreach (CompositionScopeDefinition childCatalog in _scopeDefinition.Children) { foreach (var partDefinitionAndExportDefinition in childCatalog.GetExportsFromPublicSurface(queryImport)) { // We found a match in the child catalog. Now we need to check that it doesn't get rejected. // if the rejetecion is enabled and atomic composition is present, we will actually have to do the work, if not - we just use what we have bool isChildPartRejected = false; if (_catalogExportProvider.EnsureRejection(atomicComposition)) { using (var container = CreateChildContainer(childCatalog)) { // We create a nested AtomicComposition() because the container will be Disposed and // the RevertActions need to operate before we Dispose the child container using (var localAtomicComposition = new AtomicComposition(atomicComposition)) { isChildPartRejected = container.CatalogExportProvider!.DetermineRejection(partDefinitionAndExportDefinition.Item1, localAtomicComposition); } } } // If the child part has not been rejected, we will add it to the result set. if (!isChildPartRejected) { exports.Add(CreateScopeExport(childCatalog, partDefinitionAndExportDefinition.Item1, partDefinitionAndExportDefinition.Item2)); } } } return exports; } private ScopeFactoryExport CreateScopeExport(CompositionScopeDefinition childCatalog, ComposablePartDefinition partDefinition, ExportDefinition exportDefinition) { return new ScopeFactoryExport(this, childCatalog, partDefinition, exportDefinition); } internal CompositionContainer CreateChildContainer(ComposablePartCatalog childCatalog) { return new CompositionContainer(childCatalog, _catalogExportProvider._compositionOptions, _catalogExportProvider._sourceProvider!); } private static ImportDefinition? TranslateImport(ImportDefinition definition) { IPartCreatorImportDefinition? factoryDefinition = definition as IPartCreatorImportDefinition; if (factoryDefinition == null) { return null; } // Now we need to make sure that the creation policy is handled correctly // We will always create a new child CatalogEP to satsify the request, so from the perspecitive of the caller, the policy should // always be NonShared (or Any). From teh perspective of the callee, it's the otehr way around. ContractBasedImportDefinition productImportDefinition = factoryDefinition.ProductImportDefinition; ImportDefinition? result = null; switch (productImportDefinition.RequiredCreationPolicy) { case CreationPolicy.NonShared: { // we need to recreate the import definition with the policy "Any", so that we can // pull singletons from the inner CatalogEP. teh "non-sharedness" is achieved through // the creation of the new EPs already. result = new ContractBasedImportDefinition( productImportDefinition.ContractName, productImportDefinition.RequiredTypeIdentity, productImportDefinition.RequiredMetadata, productImportDefinition.Cardinality, productImportDefinition.IsRecomposable, productImportDefinition.IsPrerequisite, CreationPolicy.Any, productImportDefinition.Metadata); break; } case CreationPolicy.Any: { // "Any" works every time result = productImportDefinition; break; } } return result; } } } }