问题
I am currently working on an MVC web app with MEF so that a) developers can develop plugins for the website, and users can elect which plugins they want on their account. This means that some of my composition has to happen after the app has already started and the user has logged in (which goes to the database, grabs the assemblies for the plug in and adds them to the current catalog).
The way it works is I have a couple of libraries that I store in the database and pull out when the user logs in to load into an AssemblyCatalog
, which I can successfully add to my existing AggregateCatalog
in my Composer. However, in one of my libraries I have an IController
contract that isn't getting exported, causing that specific widget to break. I'm not entirely sure on how to force MEF to recompose after startup. I'm posting here, hoping that someone has some advice for me.
My code is based off the excellent blog series by Matt Abbott, so I'm kind of hoping that he'll chime in with some advice as well.
回答1:
Well, couldn't you just load ALL available parts (regardless of which clients have them enabled), but use deferred instantiation, either through Lazy
or ExportFactory
with a combination of metadata to identify the parts to your client system? That way you wouldn't need to load assemblies on demand, they are just there ready to go.
If its the case that you want dynamically read an assembly from your database and load it into your AppDomain
, you can probably wrap it up in a new AssemblyCatalog
, but take advantage of recomposition.
E.g., in that early version, I was using PartCreator<T,TMetadata>
which evolved into ExportFactory<T,TMetadata>
nearing release (but not included in final .NET 4.0). If you change the [ImportMany]
to [ImportMany(AllowRecomposition = true)]
, next time you add a new catalog, e.g.:
((AggregateCatalog)container.Catalog).Catalogs.Add(<assembly>);
Which should recompose the [ImportMany]
set of PartCreator
(ExportFactory
) instances.
Not sure if that would work... I'd need to understand your intended architecture before I can say it would or would not work...
回答2:
I'm entering this as an answer, even though it's not really an answer, but more of a conclusion. My issue was this: I was doing all of my MEF composition at app startup, then trying to separate it all by user after they've logged in.
In reality, I just need to postpone all of that. Let the user log in first, THEN do all my MEF composition based on what the user has "installed" (pulling assemblies from the database, etc.), store that composition container in session or some other storage mechanism (so I can get exports as needed to construct pages, widgets, etc.), and I'm golden. My original issue arose from trying to fit a square peg into a round hole. My composition doesn't need to happen until login, not startup. Although I might use MEF to do some DI in my app, but that would be separate from user composition.
I will take this moment, though, once again to thank Matthew Abbott for his excellent series on MEF and MVC, which really helped push this application forward. :) I did not mark his answer as a reply, but I did upvote it to help give him more reputation.
来源:https://stackoverflow.com/questions/9334701/updating-mef-catalog-at-runtime