Single Part and deciding which Part to use

This relats to my previous post on unloading addins. I was thinking about using MEF for something like a logger, bascially, I want my application to have a default logger (a text file) but allow this logger to be replaced by custom loggers.

As such, I have this code which classes use to access the logger.

[Import]
public ILogger logger { get; set; }

I'm using the DirectoryPartCatalog, when it detects a new logger I wanted it to override my default logger, or the current logger, as I only want one logger available at any time.

Yes, this is by design. When you ask for only one logger, but there are multiple existing, container cannot decide which one your want.

When you expect there could be more than one logger, you should ask container to give you all loggers it find instead of just one. Then you can pick the one you want to use. Code could look like below:

[Import]
public ExportCollection<ILogger> Loggers {set; get;}

This way you are actually asking for a collection of ILogger and you also get extra benefit. You can use metadata on your different loggers to distinguish them and load only the one you want to use (aka. delay loading). Your loggers can look like below

Zhenlan,
if we get all the loggers and then choose which one we want, then are we not loading objects without using them?
My suggestion is to set a marker field that would exactly match the logger one want to use.

with that approach I could say for example,
get me a logger that will log to a database. If there is one part that supports database logging then it will be instantiated. This should be done with MEF and the calling app would only say which logger it wants to use. I guess that is what the Export metaData
attrib does

Another approach I can think of is tell the MEF to describe all the loggers it supports and then the application decides on which logger to use at what point of time.

Another thing that worries me with using the DirectoryPartCatalog is a security issue.
What if someone drops an assembly into the directory that contains malicious code. The trusted assembly could easily be swapped out.
What is your recommendation for this scenario?

Or if I don't consider using the collection approach on an Import, any additional assembly with an already existing Export will crash the application. Even with a metadata declaration I can't see a way to prevent this.

I am not sure I understand you correctly about "marker field". If you mean a field in the logger class, to use it, you have to instantiate all your loggers. However, with MEF, you only need to instantiate the one you want to use. The code
below explains this idea

// Find all database loggers
var dbLoggers = Loggers.Where(logger => logger.Metadata.Keys.Contains("Type")).Where(logger => logger.Metadata.Values.Contains("DatabaseLogger"));
// Only ask the instance of the logger you want to use. Other loggers will not be instantiated.
if (dbLoggers.Any())
{
var dbloggerObject = dbLoggers.First().GetExportedObject();
// ... do work ...
}

If you use strongly-typed metadata, the code above can be much simpler. I will leave that to you to find out. But please let us know if you have any questions.

I am with Jens on the malicious code. That is why in
fredriknormen's Blog I had suggested a registering model should be incorporated. The dependency should be on the configuration file.

To answer, no actually to question again, Zhenlan's reply. IMO, should the "discovery code" for a part,needed by an application, be left to MEF. By this I mean, that the MEF should provide a way of enuming the parts available and then allow me to
set that as a prop and instantiate an object of the type enumed.

for example,
As an app developer,
I would write something like this,

Loggers.Part = Part.Logger.Database // this is the enum

myLoggers = Loggers.getParts(); / /There might be more than one database logger. This can be finegrained by making the enum more granular.

the rest of the code that zhenlan had written should, IMO, go into the MEF. This way it will also provide a stricter way of adding parts. Only those parts enumed can be loaded.

You can add screening and filtering at the catalog level. Catalogs are the entry point in to MEF. You can for example create your own SecureDirectoryWatchingCatalog which will verify any assemblies that are loaded before they are loaded. At this point our catalogs
themselves are not really extensible so you'd have to copy our DirectoryWatchinCatalog and maybe add a virtual override. However, I have filed a bug to make sure we design in proper extensibility points.

Another approach to solving your issue is to use a property export. In the property you can filter down the one logger you want, and then just export it. The only caveat here would be you need two contracts, one for the individual loggers (I used a string)
and one for the single logger that is exported.. Building off of Zhen's example. Below is a unit test that demonstrates this. Each logger exports the "Logger" contract. Then in my LoggingProvider which is a singleton, I import the loggers, parse
out the one i want (I just took the first) and re-export it as an ILogger contract. It's transparent to the user.

Now a better approach is to actually create a custom resolver. Every export that is queried on the contianer goes throught the resolver. Within the resolver you can implement whatever policies you like. However, writing a resolver is not always an option. Also
today it's not as clean as it could be. We are planning some signficant refactoring / clean up that will make resolvers much easier to author.

How would you define the Import Attributes (that utilize ExportMetadata)?

19namespace BasicWPFApp

20 {

21///<summary>

22/// Interaction logic for Window1.xaml

23///</summary>

24 [Export("MainWindow")]

25publicpartialclassWindow1 : Window

26 {

27 [Import("DLogger")]

28publicILogger DebugLogger { get; set; }

29

30 [Import("MLogger")]

31publicILogger MessageBoxLogger { get; set; }

32

33public Window1()

34 {

35 InitializeComponent();

36 }

37

38privatevoid button1_Click(object sender, RoutedEventArgs e)

39 {

40 DebugLogger.Log("Click",

41LogCategoryType.Debug, LogPriortyType.None);

42 }

43

44privatevoid button2_Click(object sender, RoutedEventArgs e)

45 {

46 MessageBoxLogger.Log("Click",

47LogCategoryType.Debug, LogPriortyType.None);

48 }

49 }

I also found that if I move the Interface out of my .Library project into my .Interface project MEF complains during runtime - do I have to have my interface with my classes?

I would be interested in feedback on my BootStrapper class, i.e., if I'm violating any P&P for MEF. Blogged about HERE - no news is good news ;)
My blog has the fully functional source code for the above code snippets.

Q1: If you want to accept multiple you just import a collection of IMessageSenders.

I then examined the XFileExplorer views and noted that they have the same Export attribute, each with its own "index". The Import pulls a collection (consistent with Glenn's unit test) which had me thinking perhaps this is what
would supress the multiple "Logger" complaint; I'll figure it out tonight and update my demo app (and blog).

Zhenlan's Sep 11 at 10:23 PM reply is also to be taken into account if you want to selectively instantiate a particular class out of a list. The question is how would a application developer know what are the loggers available in
a library built by the "library developers"?

This is by design. MEF enforces cardinality. In your example, making both "Logger" means that you have 2 loggers. Your import is expecting a single, which one should MEF choose?

Traditional containers have a FIFO / LIFO model to choose which one to give. With MEF however, because of its discovery there is no way to choose the "First" one. Do you really want that someone dropped an assembly in the bin and the default immeidately
changed without your knowing about it? It's the indeterminate nature of such a mechanism that has led us to shy away from supporing it. MEF systems have to be consistent regardless of what is dropped in the bin.

I understand the pain thougn, and we are exploring options.

1. Have a Default attribute that flags that export for use in a single cardinality import even if there are multiple. Problem here is what if 2 Loggers have [Default].....:)
2. Have a Default catalog (separate bin folder), and then have our resolver look in the default first always if there are single imports.

Let me say clearly (and this doesn't necessarily represent the entire team). I am not a fan of you having to import the entire collection when you need one. It's feasible, but certainly not optimal. We need to come up with something (IMHO), but the
bar of success is that is must offer determinante behavior.

I am still in .net 1.1/2.0
A quick question, is the Import and Export atributes available in .net 2.0?

and now the rest:
What if my classes are compiled into a separate dll? will MEF scan through all dlls in a bin folder to figure out which are the extensibility compatible dlls?
What if I want them in different folders, say for the sake of maintainability?
Why not have an option to tell an app which dlls to look for extensibility like a key value pair in a config file?
How about at development time MEF will let me know what classes are available as extensions for a particular type?

How will I know if the production extensibilities are the same as the stage and dev env? How do I make sure of this?
How would I support different versions of the same object ?

I am not sure about the answers for all your questions, so I just try to answer what I know.

>A quick question, is the Import and Export atributes available in .net 2.0?No. The ImportAttribute/ExportAttribute are newly defined in MEF.

>What if my classes are compiled into a separate dll? will MEF scan through all dlls in a bin folder to figure out which are the extensibility compatible dlls?
No. MEF will not automatically scan your bin folder unless you ask MEF to do so - using DirectoryPartCatalog to monitor a folder or explicitly loading an assembly using AttributedAssemblyPartCatalog.

>What if I want them in different folders, say for the sake of maintainability?Use multiple DirectoryPartCatalogs (for each folder) and one AggregatingComposablePartCatalog.

>Why not have an option to tell an app which dlls to look for extensibility like a key value pair in a config file?Your app can look at the config file and load only the assemblies specified. You can also use the filter of DirectoryPartCatalogs in some extent to filter out the dlls you do not want. But I think this is a good feedback that you hope
to have some configuration capability on top of current catalog.

>How about at development time MEF will let me know what classes are available as extensions for a particular type?We also have a tooling work item planned that is supposed to address requests like this.

>How would I support different versions of the same object ?If different versions of parts are using different contracts, you can use contract adaptor to convert the old part using old contract to work with the new contract.

>Zhenlan's Sep 11 at 10:23 PM reply is also to be taken into account if you want to selectively instantiate a particular class out of a list. The question is how would a application developer know what are the loggers available
in a library built by the "library developers"?In my opinion, the app developer does not have to know. The app only looks for the loggers it expects from part libraries (the app won't work if finds nothing). It is library developers(part developers?)' responsibility to write loggers
that can be used by the target app. Of course, if loggers are already there and an app developer wants to write a new app and leverage on the existing loggers - he/she already knows what are available.

Very interesting! Is the blue box at the mid-top MEF? Could you please gave us some written description here of your diagram? (Not sure if it is a browser issue - some words in the picture are overlapped, so I cannot read).

Thanks Zhenlan for having the patience to look at the ppt. No the blue box is a mixture of MEF and Extensible Object finder ( this needs clean up)

I have done an update /cleanup/enhance to the diagram. It is now a PNG image at
My MEF

My view of MEF is to look at extensibility and usage of classes enterprise wide. This is how I envisage my architecture. I will take the now famous LOGGER as the Extensible Object.
There might be different flavors of loogers and each application in my Enterprise Biz App cluster (The Cloud) will use one / some or all of the available Loggers.

In order to get a Logger object a biz application will,

Send a message requesting for the logger through a "Conduit" to a "Extensible Object Finder" (EOFinder) (Step 1).
The EOFinder will look in its internal list (Step 2) find if there is an object available. If so , it will make a copy and send it to the biz application (Step 9)
If there is none , it will send a message to the catalog (Steps 3 and 4) to get the location of the Assembly(dll).
The catalog will return a value to identify the location of the assembly(Step 5)
The EOFinder then will send a message to load the Assembly after downloading it and the other necessary dlls(HOW does it know?) from its repository (Steps 6, 7 and 8).
A new object of the type will be instantiated and a copy of it will be sent back to the biz application(Step 9). The original will be placed in the internal list.