tags:

views:

656

answers:

5

Hi,

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?

+1  A: 

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

Luke Schafer
+6  A: 

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.

well if I knew you'd find the question I wouldn't have said anything.... :)
Luke Schafer
Nicholas Blumhardt
But only for Silverlight it would seem
TimothyP
This was added to Preview 8 for non-Silverlight and then pulled from Preview 9! Grrr.
Ray Hayes
+2  A: 

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();
Scott Whitlock
A: 

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.

Bittercoder
+1  A: 

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

That's true. But there is only one class that implements ILedPanel with any distribution of the software. So that's a single instance... it's not clean of course
TimothyP