Reputation: 21745
Currently my WPF application imports a part like this
[Import(typeof(ILedPanel)]
public ILedPanel Panel { get; set; }
But this gives ma a single intance of the class that implements ILedPanel. What I really want to do is have the ability to create as many instances that I need. Please note there is only one Export for ILedPanel included with the software at any given time.
(If I use an import with List that gives me one instance for every class implementing ILedPanel)
Any suggestions?
Upvotes: 11
Views: 9255
Reputation: 25201
All of the other answers are pretty old, so they don't mention a relatively new feature in MEF called ExportFactory
. This generic class allows you to import ExportFactory<ILedPanel>
and create as many instances as you like whenever you need them, so your code would look like this:
[Import(typeof(ILedPanel)]
public ExportFactory<ILedPanel> PanelFactory { get; set; }
public ILedPanel CreateNewLedPanelInstance()
{
return PanelFactory.CreateExport().Value;
}
This method also satisfies any imports that created part has. You can read more about using the ExportFactory
class here.
Upvotes: 11
Reputation:
There isn't "built in" support for this in MEF today, but before reverting to Service Locator, you might find some inspiration here: http://blogs.msdn.com/nblumhardt/archive/2008/12/27/container-managed-application-design-prelude-where-does-the-container-belong.aspx
The essential idea is that you 'import' the container into the component that needs to do dynamic instantiation.
More direct support for this scenario is something we're exploring.
Nick
UPDATE: MEF now has experimental support for this. See this blog post for more information.
Upvotes: 8
Reputation:
Unless I misunderstand the question, it looks like it would be solved by simply using a CreationPolicy.NonShared.
This assumes that the code declaring the Panel exists everywhere you want a panel. You would get a new instance of ILedPanel in every instance of every class that had this declaration (the import).
Upvotes: 5
Reputation: 12123
Looking at the shapes game sample that comes with MEF, there is the ShapeFactory class:
[Export]
public class ShapeFactory
{
private readonly Random random = new Random((int)DateTime.Now.Ticks);
[Import]
private ICompositionService CompositionService { get; set; }
public IShape GetRandomShape()
{
var shapeRetriever = new ShapeRetriever();
CompositionService.SatisfyImports(shapeRetriever);
int randomIndex = random.Next(shapeRetriever.PossibleShapes.Length);
return shapeRetriever.PossibleShapes[randomIndex].GetExportedObject();
}
private class ShapeRetriever
{
[ImportMany(RequiredCreationPolicy = CreationPolicy.NonShared)]
public Export<IShape, IShapeMetadata>[] PossibleShapes { get; set; }
}
}
Which demonstrates creating a random shape instances "on demand"... I would think in your scenario you could do something similar without the selection of a random implementation, as you suggest there would be only one implementation of ILedPanel registered.
Upvotes: 3
Reputation: 13839
I'm not sure if this is what Nicolas is referring to, but you could import a Factory class rather than an instance class, like this:
[Import(typeof(ILedPanelFactory)]
public ILedPanelFactory PanelFactory { get; set; }
...and then later in your code...
ILedPanel panel = PanelFactory.BuildPanel();
Upvotes: 10
Reputation: 9265
i think you mean you want to use MEF in this instance like a service locator rather than a dependency injection container. Try looking at examples for ValueResolver
Upvotes: 2