Catalogs

One of value propositions of MEF's attributed programming model is the ability to dynamically discover parts via catalogs. Catalogs allow applications to easily consume exports that have self-registered themselves via the Export attribute. Below is a list the catalogs MEF provides out of the box.

Assembly Catalog

To discover all the exports in a given assembly one would use the [System.ComponentModel.Composition.Hosting.AssemblyCatalog].

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
Dim catalog = New AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())

Directory Catalog

To discover all the exports in all the assemblies in a directory one would use the [System.ComponentModel.Composition.Hosting.DirectoryCatalog].

var catalog = new DirectoryCatalog("Extensions");
Dim catalog = New DirectoryCatalog("Extensions")

If a relative directory is used it is relative to the base directory of the current AppDomain.

The DirectoryCatalog will do a one-time scan of the directory and will not automatically refresh when there are changes in the directory. However, you can implement your own scanning mechanism, and call Refresh() on the catalog to have it rescan. Once it rescans, recomposition will occur.

var catalog = new DirectoryCatalog("Extensions");
//some scanning logic
catalog.Refresh();
Dim catalog = New DirectoryCatalog("Extensions")
'some scanning logic
catalog.Refresh()


Note: DirectoryCatalog is not supported in Silverlight.

Aggregate Catalog

When AssemblyCatalog and DirectoryCatalog are not enough individually and a combination of catalogs is needed then an application can use an [System.ComponentModel.Composition.Hosting.AggregateCatalog]. An AggregateCatalog combines multiple catalogs into a single catalog. A common pattern is to add the current executing assembly, as well as a directory catalog of third-party extensions. You can pass in a collection of catalogs to the AggregateCatalog constructor or you can add directly to the Catalogs collection i.e. catalog.Catalogs.Add(...)

var catalog = new AggregateCatalog(
  new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()), 
  new DirectoryCatalog("Extensions"));

Type Catalog

To discover all the exports in a specific set of types one would use a [System.ComponentModel.Composition.Hosting.TypeCatalog].

var catalog = new TypeCatalog(typeof(type1), typeof(type2), ...);
Dim catalog = New TypeCatalog(GetType(type1), GetType(type2) , ...) 

DeploymentCatalog - Silverlight only

MEF in Silverlight includes the DeploymentCatalog for dynamically downloading remote XAPs. For more on that see the DeploymentCatalog topic.

Using catalog with a Container

To use a catalog with the container, simpy pass the catalog to the container's constructor.

var container = new CompositionContainer(catalog);
Dim container = New CompositionContainer(catalog) 

Last edited Aug 9, 2010 at 5:23 PM by haveriss, version 15

Comments

IuriiO Apr 28, 2011 at 7:25 PM 
Typo: "simpy" -> "simply"
"To use a catalog with the container, >> simpy << pass the catalog to the container's constructor"

ONE75 Oct 27, 2010 at 1:23 PM 
@ggdani: Is it a Silverlight project? In Silverlight, the DirectoryCatalog is not available...

ggdani Oct 19, 2010 at 3:37 PM 
I'm using VS 2010 and when I try to use 'DirectoryCatalog', I receive the message:

"The type or namespace name 'DirectoryCatalog' could not be found (are you missing a using directive or an assembly reference?)"

I already included and referenced 'System.ComponentModel.Composition.Hosting' and 'System.ComponentModel.Composition'. Any idea?.

Thanks

kishore1021 Jul 29, 2010 at 2:09 PM 
Well, i guess i was looking at version4 of this documentation and i see this is corrected in the latest version. Thanks

kishore1021 Jul 29, 2010 at 2:07 PM 
In the Type Catalogs section, it is mentioned as "To discover all the exports in a specific set of types one would use a DirectoryPartCatalog.". I guess it should be TypeCatalog instead of DirectoryPartCatalog.

nblumhardt Jul 30, 2009 at 11:05 PM 
Correction - the Refresh() method (rather than AggregateCatalog) is the way to update MEF when the directory watcher fires.

nblumhardt Jul 30, 2009 at 11:02 PM 
@lancecontreras, correct. You can use a DirectoryWatcher from the .NET Framework + the AggregateCatalog to achieve this if you like. The DirectoryCatalog that shipped with earlier MEF releases might be a good place to look for example code (the older downloads are still available.)

lancecontreras Jul 24, 2009 at 6:19 AM 
Does it mean that MEF won't be supporting the watchDirectory parameter of the DirectoryCatalog? Do we have any alternative for this feature? Because right now I need something that will load and display plugin's UI to the host application.

gblock Jul 8, 2009 at 5:38 AM 
BillL I updated thanks.

BillL Jul 7, 2009 at 8:05 PM 
The Directory Catalog info needs to be corrected, as the file system watcher no longer exists in MEF.

nblumhardt Jul 7, 2009 at 3:45 PM 
Thanks for the corrections, updated now. The feature suggestions might be better posted to the discussions list.

gentledepp Jun 29, 2009 at 12:16 PM 
If i wanted to use this for plugis/addins, I'd like to watch the plugin-directory for any changes and if so, automatically start the new plugins. In that case, I'd need to either wait for all these changed plugins to shut down or kill em all and then load the new/modified versions.
Would that be doable with MEF or is it the wrong framework for that?

nadendla May 26, 2009 at 4:20 PM 
Is there a way to perform license check on imports prior to loading the assemblies?

wallyn May 20, 2009 at 2:46 PM 
A nice option would be if you added the ability to the DirectoryCatalog to search sub-directories.

fa3den Mar 27, 2009 at 8:42 PM 
The compiler can't infer the type from the inputs. Instead of "new[] {" put in "new ComposablePartCatalog[] {" and it will work.

mabster Feb 10, 2009 at 10:31 AM 
This code:

var catalog = new AggregateCatalog(new [] {
new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()),
new DirectoryCatalog("Extensions") });

Gives me a compile-time "No best type found for implicit array" error. It certainly seems like it should work, since both types derive from ComposablePartCatalog. This is with Visual C# Express 2008 SP1.