MEF1 has method ComposeExportedValue<T>(T exportedValue). MEF2 should have a similar functionality in System.Composition.Hosting.ConfigurationContainer (as discussed in dotnet/runtime#18624 and dotnet/runtime#15362)
Suggested API
public ContainerConfiguration WithInstance<TExport> (TExport instance);
public ContainerConfiguration WithInstance<TExport> (string contractName, TExport instance);
public ContainerConfiguration WithInstance (Type t, object instance);
public ContainerConfiguration WithInstance (Type t, string contractName, object instance);
(Thanks to @NEKIT-Boss for the examples in dotnet/runtime#18624)
Usage
ContainerConfiguration containerConfig = new ContainerConfiguration()
.WithAssembly(GetType().Assembly)
.WithInstance<IExample>(new Example());
var container = containerConfig.CreateContainer();
var example = container.GetExport<IExample>();
Unfortunately we have no real expertise in MEF remaining on the team. @weshaggard did you work on this code?
I'v reviewed some of the MEF2 stuff but I didn't code it. I did however code the MEF1 stuff many years ago and from what I know of MEF2 the APIs seems like they would be reasonable but I would suggest someone doing a proof of concept implementation of them before formally accepting the API proposal. The reason for that is to ensure that these fit into the model that MEF2 uses.
Thanks @weshaggard . Does anyone around have knowledge of MEF2 specifically?
I doubt there is anyone that has any recent knowledge but @nblumhardt wrote it originally and might have some memory of the code.
Hey @danmosemsft @weshaggard @gthvidsten !
This is a pretty straightforward addition; I wrote and included it as an extension WithExport() in the original MEF2 Code drop, along with another useful one, WithFactoryDelegate():
var config = new ContainerConfiguration()
.WithExport<TextWriter>(Console.Out)
.WithFactoryDelegate<string>(() => DateTime.Now.ToString(), isShared: true)
.WithPart<Program>();
The terminology WithExport() could be the some bikeshedding but as far as I remember it's the most accurate WRT the underlying model.
The demo project is here: https://github.com/MicrosoftArchive/mef/blob/master/oob/demo/Microsoft.Composition.Demos.ExtendedPartTypes/Program.cs#L24
The extension method WithExport() just adds an InstanceExportDescriptorProvider to the container:
namespace Microsoft.Composition.Demos.ExtendedPartTypes.Extension
{
static class ContainerConfigurationExtensions
{
public static ContainerConfiguration WithExport<T>(this ContainerConfiguration configuration, T exportedInstance, string contractName = null, IDictionary<string, object> metadata = null)
{
return WithExport(configuration, exportedInstance, typeof(T), contractName, metadata);
}
public static ContainerConfiguration WithExport(this ContainerConfiguration configuration, object exportedInstance, Type contractType, string contractName = null, IDictionary<string, object> metadata = null)
{
return configuration.WithProvider(new InstanceExportDescriptorProvider(
exportedInstance, contractType, contractName, metadata));
}
And the InstanceExportDescriptorProvider itself is pretty straightforward:
// we're just aiming to show the mechanics here.
class InstanceExportDescriptorProvider : SinglePartExportDescriptorProvider
{
object _exportedInstance;
public InstanceExportDescriptorProvider(object exportedInstance, Type contractType, string contractName, IDictionary<string, object> metadata)
: base (contractType, contractName, metadata)
{
if (exportedInstance == null) throw new ArgumentNullException("exportedInstance");
_exportedInstance = exportedInstance;
}
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
{
if (IsSupportedContract(contract))
yield return new ExportDescriptorPromise(contract, _exportedInstance.ToString(), true, NoDependencies, _ =>
ExportDescriptor.Create((c, o) => _exportedInstance, Metadata));
}
}
Since it's all based on the public API/extension points, you can drop this in today @gthvidsten and it should "just work".
It'd be wonderful to see this added to the official package, or included in the docs somewhere, if anyone picks it up (it still pains me that there's so much great stuff buried in this little project).
+1 vote for this feature.
Thanks for the input @nblumhardt, I've gone ahead and marked this one ready-for-review. Cheers!
I'd go with @nblumhardt's proposal, slightly adjusted:
```C#
namespace System.Composition.Hosting
{
public class ContainerConfiguration
{
public ContainerConfiguration WithExport
public ContainerConfiguration WithExport
public ContainerConfiguration WithExport(Type contractType, object exportedInstance);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance, string? contractName = null, IDictionary<string, object>? metadata = null);
}
}
```
After some discussion on the name of the methods, the use of defaults parameters, and the name of the generic, it's approved as
```C#
namespace System.Composition.Hosting
{
public class ContainerConfiguration
{
public ContainerConfiguration WithExport
public ContainerConfiguration WithExport
public ContainerConfiguration WithExport(Type contractType, object exportedInstance);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance, string? contractName = null, IDictionary<string, object>? metadata = null);
}
}
```
We also think it would be valueable to add an analyzer that warns when generic inference was used. (e.g. WithExport(new SomeExportedType()))
@gthvidsten @nblumhardt this API was approved, were either of you going to drive the implementation in? If we want this in .NET 5.0 it would need to be merged before 8/18 or sooner.
I may get a chance - a bit short of time, though, so I'll be pleased if someone else beats me to it :-)
Setting milestone to indicate this is not a required part of the 5.0 product.
Most helpful comment
Hey @danmosemsft @weshaggard @gthvidsten !
This is a pretty straightforward addition; I wrote and included it as an extension
WithExport()in the original MEF2 Code drop, along with another useful one,WithFactoryDelegate():The terminology
WithExport()could be the some bikeshedding but as far as I remember it's the most accurate WRT the underlying model.The demo project is here: https://github.com/MicrosoftArchive/mef/blob/master/oob/demo/Microsoft.Composition.Demos.ExtendedPartTypes/Program.cs#L24
The extension method
WithExport()just adds anInstanceExportDescriptorProviderto the container:And the
InstanceExportDescriptorProvideritself is pretty straightforward:Since it's all based on the public API/extension points, you can drop this in today @gthvidsten and it should "just work".
It'd be wonderful to see this added to the official package, or included in the docs somewhere, if anyone picks it up (it still pains me that there's so much great stuff buried in this little project).