-
Notifications
You must be signed in to change notification settings - Fork 5k
Proposal: Inject existing object into MEF2 #29400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
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 var config = new ContainerConfiguration()
.WithExport<TextWriter>(Console.Out)
.WithFactoryDelegate<string>(() => DateTime.Now.ToString(), isShared: true)
.WithPart<Program>(); The terminology The demo project is here: https://github.com/MicrosoftArchive/mef/blob/master/oob/demo/Microsoft.Composition.Demos.ExtendedPartTypes/Program.cs#L24 The extension method 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 // 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: namespace System.Composition.Hosting
{
public class ContainerConfiguration
{
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance);
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance, string? contractName = null, IDictionary<string, object>? metadata = null);
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 namespace System.Composition.Hosting
{
public class ContainerConfiguration
{
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance);
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance, string? contractName = null, IDictionary<string, object>? metadata = null);
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. |
@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. |
Should also close issue #27324. As the person who originally opened #15362 back in 2015, I'm glad to see this finally make it into the official packages. It drastically simplifies migration from MEF1 to MEF2 for people who don't need the flexibility of MEF1 and want to avoid the potentially higher performance cost. Refactoring a project to use plugins is a lot easier when you don't have to fully rearchitect to fit design assumptions and can just export an existing instance. I'll be glad to review my legacy projects and adjust for this. Might even have time to swap out the old handwritten context classes for |
MEF1 has method
ComposeExportedValue<T>(T exportedValue)
. MEF2 should have a similar functionality inSystem.Composition.Hosting.ConfigurationContainer
(as discussed in #18624 and #15362)Suggested API
(Thanks to @NEKIT-Boss for the examples in #18624)
Usage
The text was updated successfully, but these errors were encountered: