Thanks for getting in touch. This is a 'by design' restriction, but one we're still very much interested in feedback on.
The reason we don't currently allow dependencies to transient components at the application level is that more often than not it leads to subtle bugs and lifetime/sharing problems.
In your example, if the IResourceProvider implementations could be resolved at the application level they
could still live for the life of the application even if the ResourceCollection holds no references. This would occur if any of them implemented IDisposable, or if any disposable component imported them. Any of their disposable dependencies could also
live on forever regardless of whether ResourceCollection holds any references or not.
The only way to properly free a component at the application level is with CompositionContainer.ReleaseExport(), which is not available to most components.
This is not to say that there are problems with your scenario or implementation, so long as you are aware of all the issues it would be fine - but even so, a developer innocuously adding IDisposable or changing the composition graph down the track might
introduce subtle-but-ugly bugs into your application. Over the years working with MEF and other containers we've seen this category of bug occur again and again.
So, our thinking here was to encourage a "pit of success" by never keeping any component alive for the duration of the app unless it is marked explicitly with [ApplicationShared].
Here are the options available to you given the current setup -
- Mark the implementations of IResourceProvider as [ApplicationShared], accepting that they will hang around (so long as they don't consume resources.)
- Use custom RegistrationBuilder conventions to mark the resource providers as application shared without using the attribute and thus remaining independent of the MVC binaries (we can help to get you started.)
- Make ResourceCollection a per-request component; create another [ApplicationShared] component that it can use as a cache; take lazy dependencies on the IResourceProviders and only access/compose them if the cache has not been populated.
It will be interesting to hear how these alternatives look to you. We can appreciate there is a little more work here, but the results are going to be more robust and trouble-free in the long run. Is this workable for you, and what could we do to further
close this functionality gap without opening ourselves up to unexpected sharing/leaks?
Hope this is on the right track!