tags:

views:

91

answers:

1

Hi,

i'm playing with MEF and in the example i see this code ( i call it the MEF compose code):

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts();

In most examples this is done in the same cource file as the Startup Program class lives, as well as all of the other interfaces and classes.

Now i want to use the MEF, but i wonder what this container does. As far as i guessed it does the export / import mapping, but what if i have this code (from a windows forms app:

 [STAThread]
        static void Main()
        {
            Application.Run(new Form1());

        }

and in that Form1 i want to create an object of type Auditer (which has a property of type ILogger marked import, and i have a class implementing ILogger marked export).

Do i have to place the MEF compose code in the void Main(), in the Load event of Form1, or in the constructor of the Auditer class?

I only get it to work when i put it (the MEF compose code) in the constructor of the Auditer class, but the examples i read somehow give me the idea that you only have to call the compose code once.

+2  A: 

The CompositionContainer is the class that actually composes your parts in MEF.

When you want to use MEF, you need to always compose the part that's attributed with the import definitions. If you have a property in Form1 that's marked with [Import(typeof(ILogger))], at some point, you'll need to compose your Form1 instance.

The CompositionContainer is the class that actually performs this composition. It finds the appropriate exported ILogger based off the Catalog(s) contained within the container, and constructs types, matches exports to the imports, etc.

The reason that the MEF samples only "compose" one time is that, often, with DI, you'll have a single instance of the container constructed and setup at the beginning of the application, and it will compose your "main" window. All other classes will be composed automatically if they're being used as part of the main window. (For example, if Form1 composes an ILogger, but your ILogger implementation has an [Import] of it's own, it too will get composed in that pass.)

That being said, there is no fixed rule that specifies you can't compose more than once. In WPF and Silverlight, for example, it's frequent that MEF can't construct your object, which means it can't automatically compose your object for you. In these situations, a common pattern is to use the CompositionInitializer (in the box in Silverlight, not in the desktop) to have parts compose themselves, based off a static catalog. I recently blogged about this approach for WPF.

With Windows Forms, this may be less necessary, since there isn't a third party product (the XAML parser) constructing your types. However, you could still use this same approach, if you so choose.

Reed Copsey
Thanks for the answer. So if i understand it correct: you have to compose in the object you have the [import] statements in? So if i have 10 forms all with a import of an Ilogger and 20 other objects with an import of another interface i either have to do the composing in each form / object or have a static/global object which does the composing for all forms and objects used in the application?
Michel
@Michel: You either have to compose each object, or it needs to have been constructed via MEF directly. (If you have MEF compose A, which contains B, which contains C, and MEF constructs A, it'll automatically fill in the others...)
Reed Copsey
What i'm struggling with is where the MEF construction code lives. When i used some DI container, if i wanted to create a business object with dependencies to for example a dataclass-interface and a loggingclass-interface, i would ask a central service class to create the object for me, sort of like this: Person p = DIContainer.Resolve<Person> So in that case there was a central component/class that had the 'knowledge' of all the interfaces and concrete types. Is that also the case in a typical MEF application, or does the Person class itself construct it dependencies (via MEF)?
Michel
@Michel: WHat you're describing is the classic Service Locator pattern. MEF ~can~ work this way, to some extent, but it is not intended to work this way. Instead, it uses Dependency Injection. This pattern has been found to be "better" over time, since it makes the injected types more visible, which means it's easier to mock out for testing, etc.
Reed Copsey
@Reed: do you have a (link to) good example project, because i don't think i actually get it :)
Michel
@Michel: Have you looked at the MEF sample projects on codeplex (ie: MEFlook)? They show off the DI pattern pretty well.
Reed Copsey
Not yet, but i will now. Thanks again.
Michel