|
// 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.Collections.ObjectModel;
using System.Linq;
namespace System.Composition.Hosting.Core
{
/// <summary>
/// Represents an export descriptor that an available part can provide.
/// </summary>
/// <remarks>This type is central to the cycle-checking, adaptation and
/// compilation features of the container.</remarks>
public class ExportDescriptorPromise
{
private readonly string _origin;
private readonly bool _isShared;
private readonly Lazy<ReadOnlyCollection<CompositionDependency>> _dependencies;
private readonly Lazy<ExportDescriptor> _descriptor;
private readonly CompositionContract _contract;
private bool _creating;
/// <summary>
/// Create a promise for an export descriptor.
/// </summary>
/// <param name="origin">A description of where the export is being provided from (e.g. the part type).
/// Used to provide friendly errors.</param>
/// <param name="isShared">True if the export is shared within some context, otherwise false. Used in cycle
/// checking.</param>
/// <param name="dependencies">A function providing dependencies required in order to fulfill the promise.</param>
/// <param name="getDescriptor">A function providing the promise.</param>
/// <param name="contract">The contract fulfilled by this promise.</param>
/// <seealso cref="ExportDescriptorProvider"/>.
public ExportDescriptorPromise(
CompositionContract contract,
string origin,
bool isShared,
Func<IEnumerable<CompositionDependency>> dependencies,
Func<IEnumerable<CompositionDependency>, ExportDescriptor> getDescriptor)
{
_contract = contract;
_origin = origin;
_isShared = isShared;
_dependencies = new Lazy<ReadOnlyCollection<CompositionDependency>>(() => new ReadOnlyCollection<CompositionDependency>(dependencies().ToList()), false);
_descriptor = new Lazy<ExportDescriptor>(() => getDescriptor(_dependencies.Value), false);
}
/// <summary>
/// A description of where the export is being provided from (e.g. the part type).
/// Used to provide friendly errors.
/// </summary>
public string Origin { get { return _origin; } }
/// <summary>
/// True if the export is shared within some context, otherwise false. Used in cycle
/// checking.
/// </summary>
public bool IsShared { get { return _isShared; } }
/// <summary>
/// The dependencies required in order to fulfill the promise.
/// </summary>
public ReadOnlyCollection<CompositionDependency> Dependencies { get { return _dependencies.Value; } }
/// <summary>
/// The contract fulfilled by this promise.
/// </summary>
public CompositionContract Contract { get { return _contract; } }
/// <summary>
/// Retrieve the promised export descriptor.
/// </summary>
/// <returns>The export descriptor.</returns>
public ExportDescriptor GetDescriptor()
{
if (_creating && !_descriptor.IsValueCreated)
return new CycleBreakingExportDescriptor(_descriptor);
_creating = true;
try
{
ExportDescriptor relay = _descriptor.Value;
if (relay == null)
{
throw new ArgumentNullException("descriptor");
}
return relay;
}
finally
{
_creating = false;
}
}
/// <summary>
/// Describes the promise.
/// </summary>
/// <returns>A description of the promise.</returns>
public override string ToString()
{
return SR.Format(SR.ExportDescriptor_ToStringFormat, Contract, Origin);
}
}
}
|