| File: System\ComponentModel\Composition\Hosting\CatalogExportProvider.CatalogExport.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.ComponentModel.Composition.Primitives; using System.Diagnostics.CodeAnalysis; using System.Threading; namespace System.ComponentModel.Composition.Hosting { public partial class CatalogExportProvider { private class CatalogExport : Export { protected readonly CatalogExportProvider _catalogExportProvider; protected readonly ComposablePartDefinition _partDefinition; protected readonly ExportDefinition _definition; public CatalogExport(CatalogExportProvider catalogExportProvider, ComposablePartDefinition partDefinition, ExportDefinition definition) { _catalogExportProvider = catalogExportProvider; _partDefinition = partDefinition; _definition = definition; } public override ExportDefinition Definition { get { return _definition; } } protected virtual bool IsSharedPart { get { return true; } } protected CatalogPart GetPartCore() { return _catalogExportProvider.GetComposablePart(_partDefinition, IsSharedPart); } protected void DisposePartCore(CatalogPart part, object? value) { _catalogExportProvider.DisposePart(value, part, null); } protected virtual CatalogPart GetPart() { return GetPartCore(); } protected override object? GetExportedValueCore() { return _catalogExportProvider.GetExportedValue(GetPart(), _definition, IsSharedPart); } public static CatalogExport CreateExport(CatalogExportProvider catalogExportProvider, ComposablePartDefinition partDefinition, ExportDefinition definition, CreationPolicy importCreationPolicy) { CreationPolicy partPolicy = partDefinition.Metadata.GetValue<CreationPolicy>(CompositionConstants.PartCreationPolicyMetadataName); bool isSharedPart = ShouldUseSharedPart(partPolicy, importCreationPolicy); if (isSharedPart) { return new CatalogExport(catalogExportProvider, partDefinition, definition); } else { return new NonSharedCatalogExport(catalogExportProvider, partDefinition, definition); } } private static bool ShouldUseSharedPart(CreationPolicy partPolicy, CreationPolicy importPolicy) { // Matrix that details which policy to use for a given part to satisfy a given import. // Part.Any Part.Shared Part.NonShared // Import.Any Shared Shared NonShared // Import.Shared Shared Shared N/A // Import.NonShared NonShared N/A NonShared switch (partPolicy) { case CreationPolicy.Any: { if (importPolicy == CreationPolicy.Any || importPolicy == CreationPolicy.Shared) { return true; } return false; } case CreationPolicy.NonShared: { if (importPolicy == CreationPolicy.Shared) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } return false; } default: { if (partPolicy != CreationPolicy.Shared || importPolicy == CreationPolicy.NonShared) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } return true; } } } } private sealed class NonSharedCatalogExport : CatalogExport, IDisposable { private CatalogPart? _part; private readonly object _lock = new object(); public NonSharedCatalogExport(CatalogExportProvider catalogExportProvider, ComposablePartDefinition partDefinition, ExportDefinition definition) : base(catalogExportProvider, partDefinition, definition) { } protected override CatalogPart GetPart() { // we need to ensure that the part gets created only once, as the export contract requires that the same value be returned on subsequent calls if (_part == null) { CatalogPart? part = GetPartCore(); lock (_lock) { if (_part == null) { Thread.MemoryBarrier(); _part = part; part = null; } } if (part != null) { DisposePartCore(part, null); } } return _part; } protected override bool IsSharedPart { get { return false; } } void IDisposable.Dispose() { if (_part != null) { DisposePartCore(_part, Value); _part = null; } } } } }