1

I had a simple implementation of MEF loading some dlls (plugins) from a directory. This was running well under MEF1 but now I want to use the same functionality with MEF2 and it gives me an IEnumerable that contains the right count of dlls that are in the directory but all the assemblies the same.

For example I have two assemblies: fakeplugin1.dll and fakeplugin2.dll in the directory. They exports FakePlugin1 and FakePlugin2 classes. Now when I call container.ComposeParts() I don't have anything in the list decorated with ImportMany and container.Catalog contains two assemblies in the directory but both of them are FakePlugin1.

Here's the code:

[ImportMany(typeof (IDCPlugin))]
        IEnumerable<IDCPlugin> workplaceControllers;
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
var agcatalogue = new AggregateCatalog(catalog);
var container = new CompositionContainer(agcatalogue);
container.ComposeParts();

I am trying to use ExportFactory and RegistrationBuilder but I've just realized that even the base functionality donesn't work as expected.

What am I doing wrong? Has something changed in MEF2 I should know? How to load the two different assemblies? :)

Thanks for your help in advance!

Edit: It always creates two instances of the first type in the folder (ascending in abc). If I put an other one in the folder it creates three of the same, etc.

Edit: I have uploaded code to pastebin that gives the same result with MEF2: http://pastebin.com/3fWcujPS

Perrier
  • 2,753
  • 5
  • 33
  • 53

1 Answers1

1

A catalog will contain Import and Export definitions for anything detected. Regardless of if you actually need it.

This is a 'feature' of MEF. You will need to either ImportMany and selectively filter the plugins you require.

So how do you handle multiple plugins gracefully? Try this:

[Export]
public class PluginService
{
   public const string BEST_PLUGIN = "BestPlugin";

   [ImportMany]
   public IEnumerable<Plugin> Plugins{ private get; set; }

   [Export(BEST_PLUGIN)]
   public Plugin BestPlugin{ get { return GetBestPlugin(); } }

   Plugin GetBestPlugin()
   {
       return Plugins.FirstOrDefault(); //or some other logic for selection
   }
}

If your plugins are resource intensive, you may want to consider Lazy initialization.

Lazy<T, TMetadata> is a type provided by MEF to hold indirect references to exports. Here, in addition to the exported object itself, you also get export metadata, or information that describes the exported object. Each Lazy<T, TMetadata> contains an IOperation object, representing an actual operation, and an IOperationData object, representing its metadata.

http://msdn.microsoft.com/en-us/library/dd460648.aspx#further_imports_and_importmany

MEF has strong rules on component cardinality (number of things) to ensure that there are never any surprises but this does mean you have to be careful with your deployment.

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • Thanks. But why have I got the same types imported more times instead of all types once? – Perrier Oct 09 '13 at 13:06
  • 1
    Silly question: Are you absolutely sure that the two files are different assemblies? – Gusdor Oct 09 '13 at 13:14
  • :) Of course. I build them from the same project but rename the class, rewrite two properties and build. I then rename the file and make an other one. Always the first one will be the class that is imported in abc ascending order. I've even tried to make this two different assemblies and rename the one in the project but that has no effect. It reads just those are in the directory. – Perrier Oct 09 '13 at 13:21
  • I have edited the post with a link to the MEF2 approach on pastebin. – Perrier Oct 09 '13 at 13:32
  • Unfortunately you were right: I have made a completely different solution and project, imported the needed references and copied the dll to the directory of the other project. Now it works as expected but I still don't know, why were the other assemblies the same. Even if I looked into the bineries I have found the renamed class names. Anyway, thanks for the silly question. ;) – Perrier Oct 09 '13 at 14:04
  • @Perrier Great success! – Gusdor Oct 09 '13 at 14:45