Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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();

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.

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).

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top