I\'m attempting to create a framework for allowing controllers and views to be dynamically imported into an MVC application. Here\'s how it works so far:
The imported libaries aren't in the /bin
directory so aren't probed when trying to resolve references. I discovered a work around which I published in my MVC + MEF article (Part 2). Essentially you need to add your directories where your extensions sit to the probing path of the AppDomain.
Essentially where I am building my container:
///
/// Creates the composition container.
///
///
protected virtual CompositionContainer CreateCompositionContainer()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(MapPath("~/bin")));
var config = CompositionConfigurationSection.GetInstance();
if (config != null && config.Catalogs != null) {
config.Catalogs
.Cast()
.ForEach(c =>
{
if (!string.IsNullOrEmpty(c.Path)) {
string path = c.Path;
if (path.StartsWith("~"))
path = MapPath(path);
foreach (var directoryCatalog in GetDirectoryCatalogs(path)) {
// Register our path for probing.
RegisterPath(directoryCatalog.FullPath);
// Add the catalog.
catalog.Catalogs.Add(directoryCatalog);
}
}
});
}
var provider = new DynamicInstantiationExportProvider();
var container = new CompositionContainer(catalog, provider);
provider.SourceProvider = container;
return container;
}
I register all the directories of catalogs in the current domain:
///
/// Registers the specified path for probing.
///
/// The probable path.
private void RegisterPath(string path)
{
AppDomain.CurrentDomain.AppendPrivatePath(path);
}
I believe the same should work for MVC3.
UPDATE: Correct me if I am wrong, but I don't believe that ViewEngines are instantiated once per request, you create a single instance that you register with MVC. Because of this only one IModule
instance is ever used with your ViewEngine, so if a path doesn't match that first IModule.Name
it won't be found? Does that make sense?