How to enumerate assemblies within AggregateCatalog or DirectoryCatalog in MEF?

StackOverflow https://stackoverflow.com/questions/859423

  •  21-08-2019
  •  | 
  •  

Question

I have a MEF (Microsoft Extension Framework) application which loads some assemblies from a folder. I need to enumerate the assemblies that produced any exports for my application.

One way to do it is to enumerate imports calling GetExportedObject().GetType().Assembly. But it would be cleaner to do this without instantiation of imports. Is there a way to get loaded assemblies from a catalog or anything else?

I need assemblies to get their attributes like copyright, version, name and such. My folder can contain both assemblies with exports and without ones, but I need only assemblies that satisfied any imports in the app.

Was it helpful?

Solution

The AssemblyCatalog has an Assembly property. The AggregateCatalog does not have a way to get this information directly- there's no guarantee that the inner catalogs even load their parts from an assembly. The DirectoryCatalog doesn't have this capability although it might be possible to add it if there was a good reason.

Why do you want to get the list of assemblies? You may be better off not using a directory catalag, instead just scan and load the assemblies in a directory yourself, and create an AssemblyCatalog for each one and add it to an AggregateCatalog.

EDIT: MEF doesn't have a way of getting a list of all the exports that were "used" in composition. You could probably write your own catalog which would return part definitions that were shells around the default part definitions and kept track of which parts had GetExportedObject called on them. You can use the APIs in ReflectionModelServices to figure out which type corresponds to a given part definition from the default catalogs. Note that writing such a catalog would probably not be a simple undertaking.

OTHER TIPS

This is one way of doing it, and is used in Caliburn.Micro:

var aggregateCatalog = new AggregateCatalog(...);
var assemblies = aggregateCatalog.Parts
    .Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
    .Distinct()
    .ToList();

Here is my current solution that works nicely:

  1. Do not use DirectoryCatalog, load assemblies directly and create an AssemblyCatalog from them.
  2. Use AssemblyCatalog.Parts to find out which assemblies have exports, let the user authorize them.
  3. Add only authorized AssemblyCatalog's to the AggregateCatalog, which is ised in the composition.

If you have access to source of those assemblies then I have an alternative solution to adding assemblies one by one. You can create an interface called IModule and make it a requirement for all of your assemblies to Export that. Then you can ImportAll them into your bootstraper:

[ImportMany]
public List<IModule> Modules { get; set; }

This list will contain a list of all Module classes through which you can access the assembly:

var module1 = Logic.Instance.Modules[0];
var fullename = module1.GetType().Assembly.FullName;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top