How to enumerate assemblies within AggregateCatalog or DirectoryCatalog in MEF?
Asked Answered
T

4

5

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.

Trip answered 13/5, 2009 at 17:55 Comment(0)
W
2

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.

Wystand answered 13/5, 2009 at 18:51 Comment(2)
I've updated the question on why I need the assemblies. Actually, even having DirectoryCatalog return the assemblies wouldn't solve my goal because the list might contain MEF dll's which have nothing to do with my imports. If I could get the assembly from Export without calling the GetExportedObject, or have the satisfied imports assemblies some other way...Trip
I'll add that I need this same sort of functionality. I'm integrating with another system that uses the BuildManager and I want to add assemblies that I'm using with MEF to the BuildManager.Screenplay
T
7

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();
Tsosie answered 10/6, 2014 at 18:14 Comment(2)
best answer! via this way I can keep using a DirectoryCatalog and still get a list of all the assemblies that were loaded (the Parts) via MEF. In the code above I've changed AggregateCatalog to DirectoryCatalog.Bugger
Thank you! This saved me a lot of strife. I knew there must be some way to get more info from that poor Parts list.Money
W
2

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.

Wystand answered 13/5, 2009 at 18:51 Comment(2)
I've updated the question on why I need the assemblies. Actually, even having DirectoryCatalog return the assemblies wouldn't solve my goal because the list might contain MEF dll's which have nothing to do with my imports. If I could get the assembly from Export without calling the GetExportedObject, or have the satisfied imports assemblies some other way...Trip
I'll add that I need this same sort of functionality. I'm integrating with another system that uses the BuildManager and I want to add assemblies that I'm using with MEF to the BuildManager.Screenplay
T
2

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.
Trip answered 15/10, 2010 at 20:25 Comment(0)
V
0

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;
Verminous answered 31/10, 2013 at 17:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.