Multiple Instances

Nov 1, 2008 at 9:43 AM
Hi
I am using at ExportCollection like:
[Import("PresenterContract")]
ExportCollection<Presenter, PresenterMetadata> _presenter;


Later in the code in the code..

Presenter presenter = _presenter[i].GetExportedObject()


It seems to me that I always gets the same instance of the Presenter class. My purpose was to create different instances.

Any tip where I goes wrong?

//regards
//lasse
Nov 1, 2008 at 5:41 PM
Hi
Found the answer on my own question.

[

CompositionOptions(CreationPolicy = CreationPolicy.Factory)]
[Export("PresenterContract")]

 

 

...did the trick.


//lasse

Coordinator
Nov 3, 2008 at 5:30 PM
Please note that this behavior will change in the future.  For a given instance of Export, (or Export<T> or Export<T,M>), GetExportedObject will always return the same object.  The creation policy will affect whether different instances of the Export class are created each time it is requested.  To get multiple objects, you could put PresenterFactories instead of Presenters in the container, or you could call container.GetExports<Presenter, PresenterMetadata> each time you want new instances.

Thanks,
Daniel
Nov 8, 2008 at 9:43 AM
ok,, I guess this is managable,,, but i vill cearternly add complexity to my code, because most if my "Exports" are of "type" multiple instances. It is only in rare occations that I use "singelton" classes. What is the resason for changing this?? 
 
//lasse 
Nov 10, 2008 at 1:05 PM
Hi Daniel,

Are you saying not to use the CompositionOptions as suggested by lasse?  Not sure that I follow what you are saying, I have attempted what you have suggested (call container.GetExports each time) but that doesn't seem to help me.  Could you please expand a little, and perhaps provide an example to demonstrate?

I have a similar problem I am trying to solve but I keep getting a singleton returned.

Thanks
Dec 17, 2008 at 12:00 AM
I am really new to MEF and I'm still trying to understand how to create multiple instances of a given class.  For example, say I have an assembly (.dll) that contains a decorated MEF export called SpecificOnOffDevice that implements IOnOffDevice (which exists in a shared library).  If my hosting application (that imports the IOnOffDevice interface) needs 30 SpecificOnOffDevice instances, how would I go about getting/creating those?  Along with that, how would I be able to retreive them later once they are created?  I would really appreciate any help on this.

Thanks!
Joel
Dec 17, 2008 at 12:42 AM
Hi Joel

It sounds like what you want to do is spin up 30 different instances of an IOnOffDevice.

If that is the case you can do that by making SpecificOnOffDevice export IOnOffDevice as a factory. To make it a factory, decorate the SpecificOnOffDevice class (in addition to the export attribute) with [CompositionOptions(CreationPolicy = CreationPolicy.Factory]). Once you have declared it as a factory, you can call GetExportedObject method on the container 30 times to create new instances. Once you created the new instances you would need to manage them as the container would not allow you to retrieve them.

Another approach (if you have defined SpecificOnOffDevice as a factory) for getting the instances created, is to have a part import IOnOffDevice and then you create that part, manually add it to the container, and compose it.

For example you could create a job class.

[Export]
public class Job {
  [Import]
  IOnOffDevice Device {get;set;} 
}

Then in the code when you need to create a job you would write the following code.

public Job CreateJob() {
  var job = new Job();
  container.Add(job) //assumes you have access to a Composition Container
  container.Compose();
  return job;
}

If you call CreateJob() 30 times, it will create 30 jobs that each have 30 devices.

Dec 17, 2008 at 12:45 AM
Edited Dec 17, 2008 at 12:46 AM
@tqc What Daniel is saying is that the behavior of GetExportedObject will change (actually has changed in our Preview 3 drop). Previously when you declared something as a factory using CompositionOptions, and then imported an Export<Foo>, each call to GetExportedObject would give you a new Foo. With the changes GetExportedObject on an Export will return the same instance in successive calls. Either way you still need CompositionOptions to declare a factory.
Dec 18, 2008 at 2:47 PM
Glenn,

Thanks so much for responding to my question so quickly.  I understand what you are saying for the first approach and mostly understand for the second approach.  I think what you meant to say is that if I call CreateJob() 30 times, I will have 30 job objects with one SpecificOnOffDevice each.  Is that correct?

One other question I have is what if I have multiple classes that implement IOnOffDevice.  How would I specify which one I wanted to create?  For example, say I have a SerialOnOffDevice, a TCPOnOffDevice, and a UDPOnOffDevice that all implement IOnOffDevice.  They each also have the [Export(typeof(IOnOffDevice))] attribute attached to the class.  If I wanted to make 2 instances of SerialOnOffDevice, one instance of TCPOnOffDevice, and one instance of UDPOnOffDevice, how would I do that?

Thanks for you help!
Joel
Dec 19, 2008 at 1:37 AM
Instead of exporting IOnOffDevice, you could export the concrete device types. To do that just use the default overload ([Export]) without passing in any contract info. You can then query the container for the specific ones you want created using code similar to below (assuming all the exports are factories).

container.GetExportedObject<SerialOnOffDevice>() //creates a new SerialOnOffDevice
container.GetExportedObject<TCPOnOffDevice>() //creates a new TCPOnOffDevice

Can you give me more details of exactly what you are trying to do...(the bigger picture). It's hard to say which approach is the best without knowing what you are planning to use the devices for. For example:
 
Are they getting injected into things that use them, or do you manually work with them once you have them?
Do the devices have additional imports on them?

Thanks
Glenn