Question

I'm using MEF (the one in .Net Framework, not System.Composition Nuget) to do DI in asp.net. I'm encountering memory leaks like many have previously due to MEF rooting NonShared IDisposable (e.g. link)

I'm looking at using child containers to rectify this by having

  • Child containers create (NonShared) parts specific to a single request
  • Parent container (referenced as an export provider) containing the shared parts

So something like:

CompositionContainer GetRequestContainer(CompositionContainer parent, ComposablePartCatalog catalog)
{
    return new CompositionContainer(catalog, parent);
}

Originally, I built a single catalog with Shared and Non-Shared parts: To create a child container with only NonShared parts I used FilteredCatalogs built off the parent CompositionContainer's catalog so that the filtered catalog contains only the NonShared parts.

This resolved the memory leak since I could Dispose() the child container at the end of a request whcih would then free up all my NonShared IDisposable objects. Great.

However, calling childContainer.GetExportValues returns duplicates because there are parts from the parent containers catalog as well as the child container's catalog.


Now I want to create 2 catalogs explicitly:

  • Global catalog for all shared parts
  • Local catalog for all NonShared parts

I suspect the IDisposable tracking is at the container level so I should be safe passing around single instance of each catalog, but that is what I wanted to ask here and confirm:

Is it threadsafe to have a single instance of a catalog backing all instances of containers?

So N concurrent WebRequest instances are serviced by N + 1 CompositionContainer instances (child+parent), all backed by 2 global catalog instances.

CompositionContainer parent = new CompositionContainer(Static.Global, CompositionOptions.IsThreadSafe);

CompositionContainer GetRequestContainer(CompositionContainer parent)
{
    return new CompositionContainer(Static.Local, parent);
}
Was it helpful?

Solution

It is perfectly safe to use the same catalog instance with several CompositionContainer instances (by the way, this is true regardless of whether you use the CompositionOptions.IsThreadSafe option when creating your container).

The reason it's safe to do so is because the catalog merely defines the "potential" of parts that can be created by the container, and doesn't hold any data regarding whether they have been instantiated or not. It's the container's responsibility to track such things.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top