diff --git a/src/libraries/System.Composition.TypedParts/src/System.Composition.TypedParts.csproj b/src/libraries/System.Composition.TypedParts/src/System.Composition.TypedParts.csproj
index c1e5ea140663c..18a65ddf10137 100644
--- a/src/libraries/System.Composition.TypedParts/src/System.Composition.TypedParts.csproj
+++ b/src/libraries/System.Composition.TypedParts/src/System.Composition.TypedParts.csproj
@@ -18,6 +18,8 @@ System.Composition.Hosting.ContainerConfiguration
+
+
diff --git a/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/ContainerConfiguration.cs b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/ContainerConfiguration.cs
index 9c2f37764aab2..7db5b2c541a5e 100644
--- a/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/ContainerConfiguration.cs
+++ b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/ContainerConfiguration.cs
@@ -197,6 +197,54 @@ public ContainerConfiguration WithAssemblies(IEnumerable assemblies!!,
return WithParts(assemblies.SelectMany(a => a.DefinedTypes.Select(dt => dt.AsType())), conventions);
}
+ ///
+ /// Add a single instance to the container.
+ ///
+ /// The type of the contract of the instance.
+ /// The instance to add to the container.
+ /// A configuration object allowing configuration to continue.
+ public ContainerConfiguration WithExport(TExport exportedInstance!!)
+ {
+ return WithExport(exportedInstance, null, null);
+ }
+
+ ///
+ /// Add a single instance to the container.
+ ///
+ /// The type of the contract of the instance.
+ /// The instance to add to the container.
+ /// Optionally, a name that discriminates this contract from others with the same type.
+ /// Optionally, a non-empty collection of named constraints that apply to the contract.
+ /// A configuration object allowing configuration to continue.
+ public ContainerConfiguration WithExport(TExport exportedInstance!!, string contractName = null, IDictionary metadata = null)
+ {
+ return WithExport(typeof(TExport), exportedInstance, contractName, metadata);
+ }
+
+ ///
+ /// Add a single instance to the container.
+ ///
+ /// The type of the contract of the instance.
+ /// The instance to add to the container.
+ /// A configuration object allowing configuration to continue.
+ public ContainerConfiguration WithExport(Type contractType!!, object exportedInstance!!)
+ {
+ return WithExport(contractType, exportedInstance, null, null);
+ }
+
+ ///
+ /// Add a single instance to the container.
+ ///
+ /// The type of the contract of the instance.
+ /// The instance to add to the container.
+ /// Optionally, a name that discriminates this contract from others with the same type.
+ /// Optionally, a non-empty collection of named constraints that apply to the contract.
+ /// A configuration object allowing configuration to continue.
+ public ContainerConfiguration WithExport(Type contractType!!, object exportedInstance!!, string contractName = null, IDictionary metadata = null)
+ {
+ return WithProvider(new InstanceExportDescriptorProvider(exportedInstance, contractType, contractName, metadata));
+ }
+
internal ExportDescriptorProvider[] DebugGetAddedExportDescriptorProviders()
{
return _addedSources.ToArray();
diff --git a/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/InstanceExportDescriptorProvider.cs b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/InstanceExportDescriptorProvider.cs
new file mode 100644
index 0000000000000..5a7122bd3217d
--- /dev/null
+++ b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/InstanceExportDescriptorProvider.cs
@@ -0,0 +1,26 @@
+// 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.Composition.Hosting.Core;
+
+namespace System.Composition.Hosting
+{
+ internal class InstanceExportDescriptorProvider : SinglePartExportDescriptorProvider
+ {
+ private readonly object _exportedInstance;
+
+ public InstanceExportDescriptorProvider(object exportedInstance, Type contractType, string contractName, IDictionary metadata)
+ : base(contractType, contractName, metadata)
+ {
+ _exportedInstance = exportedInstance;
+ }
+
+ public override IEnumerable GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
+ {
+ if (IsSupportedContract(contract))
+ yield return new ExportDescriptorPromise(contract, _exportedInstance.ToString(), true, NoDependencies, _ =>
+ ExportDescriptor.Create((c, o) => _exportedInstance, Metadata));
+ }
+ }
+}
diff --git a/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/SinglePartExportDescriptorProvider.cs b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/SinglePartExportDescriptorProvider.cs
new file mode 100644
index 0000000000000..f20a694151d26
--- /dev/null
+++ b/src/libraries/System.Composition.TypedParts/src/System/Composition/Hosting/SinglePartExportDescriptorProvider.cs
@@ -0,0 +1,43 @@
+// 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.Composition.Hosting.Core;
+using System.Linq;
+
+namespace System.Composition.Hosting
+{
+ internal abstract class SinglePartExportDescriptorProvider : ExportDescriptorProvider
+ {
+ private readonly Type _contractType;
+ private readonly string _contractName;
+
+ protected SinglePartExportDescriptorProvider(Type contractType, string contractName, IDictionary metadata)
+ {
+ _contractType = contractType;
+ _contractName = contractName;
+ Metadata = metadata ?? new Dictionary();
+ }
+
+ protected bool IsSupportedContract(CompositionContract contract)
+ {
+ if (contract.ContractType != _contractType ||
+ contract.ContractName != _contractName)
+ return false;
+
+ if (contract.MetadataConstraints != null)
+ {
+ var subsetOfConstraints = contract.MetadataConstraints.Where(c => Metadata.ContainsKey(c.Key)).ToDictionary(c => c.Key, c => Metadata[c.Key]);
+ var constrainedSubset = new CompositionContract(contract.ContractType, contract.ContractName,
+ subsetOfConstraints.Count == 0 ? null : subsetOfConstraints);
+
+ if (!contract.Equals(constrainedSubset))
+ return false;
+ }
+
+ return true;
+ }
+
+ protected IDictionary Metadata { get; }
+ }
+}
diff --git a/src/libraries/System.Composition.TypedParts/tests/ContainerConfigurationTests.cs b/src/libraries/System.Composition.TypedParts/tests/ContainerConfigurationTests.cs
index 7e1d7bf6cf78e..4c9e9253bdcee 100644
--- a/src/libraries/System.Composition.TypedParts/tests/ContainerConfigurationTests.cs
+++ b/src/libraries/System.Composition.TypedParts/tests/ContainerConfigurationTests.cs
@@ -254,6 +254,42 @@ public void WithAssemby_Null_ThrowsNullReferenceExceptionOnCreation()
Assert.Throws(() => configuration.CreateContainer());
}
+ [Fact]
+ public void WithExport_Base_Success()
+ {
+ var instance = new Base();
+
+ var configuration = new ContainerConfiguration();
+ Assert.Same(configuration, configuration.WithExport(instance));
+
+ CompositionHost container = configuration.CreateContainer();
+ Assert.Same(instance, container.GetExport());
+ }
+
+ [Fact]
+ public void WithExport_Derived_Success()
+ {
+ var instance = new Derived();
+
+ var configuration = new ContainerConfiguration();
+ Assert.Same(configuration, configuration.WithExport(instance));
+
+ CompositionHost container = configuration.CreateContainer();
+ Assert.Same(instance, container.GetExport());
+ }
+
+ [Fact]
+ public void WithExport_ContractName_Success()
+ {
+ var instance = new Base();
+
+ var configuration = new ContainerConfiguration();
+ Assert.Same(configuration, configuration.WithExport(instance, "Contract"));
+
+ CompositionHost container = configuration.CreateContainer();
+ Assert.Same(instance, container.GetExport("Contract"));
+ }
+
[Fact]
public void CreateContainer_ExportedSubClass_Success()
{