MEF y MVC 3: ¿cómo cargar vistas incrustadas dinámicamente desde el contenedor mef?

Estoy creando una aplicación MVC 3 donde se usa MEF. La idea principal es tener un mecanismo de complemento donde los modelos, controladores y vistas se carguen dinámicamente durante el tiempo de ejecución desde el contenedor mef.

Cada complemento / módulo consta de dos conjuntos:

Module1.Data.dll (contiene definiciones de modelos) Module1.Web.dll (contiene controladores y vistas)

y se colocan en el directorio de Complementos dentro del bin de la aplicación web:

WebApp / Bin / Plugins / Module1.Data.dll WebApp / Bin / Plugins / Module1.Web.dll WebApp / Bin / Plugins / Module2.Data.dll WebApp / Bin / Plugins / Module2.Web.dll WebApp / Bin / Plugins / ModuleCore.Data.dll WebApp / Bin / Plugins / ModuleCore.Web.dlletc ...

También hay un módulo central al que hacen referencia todos los demás módulos: ModuleCore.Data.dll y ModuleCore.Web.dll, respectivamente.

A continuación, en Global.asax, el contenedor se construye de la siguiente manera:

AggregateCatalog catalog = new AggregateCatalog();
var binCatalog = new DirectoryCatalog(HttpRuntime.BinDirectory, "Module*.dll");
var pluginsCatalot = new DirectoryCatalog(Path.Combine(HttpRuntime.BinDirectory, "Plugins"), "Module*.dll");
catalog.Catalogs.Add(binCatalog);
catalog.Catalogs.Add(pluginsCatalot);
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
AppDomain.CurrentDomain.AppendPrivatePath(Path.Combine(HttpRuntime.BinDirectory, "Plugins"));

CustomViewEngine se crea y registra y se utiliza paraencontrando vistas en el ensamblaje del módulo:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());

controller factory para cargar controladores desde el contenedor:

ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(_container));

y también proveedor de ruta virtual personalizado para obtener ensamblados desde el contenedor:

HostingEnvironment.RegisterVirtualPathProvider(new ModuleVirtualPathProvider());

Ok, entonces toda la infraestructura para manejar modelos conectables, controladores y vistas está lista. Ahora todo funciona ... excepto una cosa: Vistas fuertemente escritas.

Para ilustrar el problema con más detalles, preparemos la escena:

l modelo @UserDTO se encuentra en Module1.Data.dll ShowUserController.cs se encuentra en Module1.Web.dll / Controllers / Index.cshtml se encuentra en Module1.Web.dll / Views / ShowUser (con el @model declarado Module1.Data.UserDto)

Ahora hacemos lo siguiente:

Ejecute la aplicación y vaya a HOST / ShowUser / Index (el método de acción Index se ejecuta en ShowUserController y se obtiene Index.cshtml)Después de recuperar la vista Index.cshtml - comienza la compilación (por RazorBuildProvider)e lanzan @Exceptions: "no se puede encontrar el tipo de datos en el espacio de nombres Módulo1", en otras palabras, no se pudo encontrar UserDTO durante la creación dinámica de la vista

e modo que parece que el compilador / constructor no buscó en la carpeta bin / Plugins para Module1.Data.dll, porque cuando copié este archivo en la carpeta bin, estaba bien redactado.

Pregunta / problema: ¿por qué el generador no buscó en la carpeta bin / Plugins a pesar de que este directorio fue agregado por el método AppDomain.CurrentDomain.AppendPrivatePath? ¿Cómo agregar rutas privadas para el generador de ensamblaje una vez para que la carpeta de complementos se tenga en cuenta?

He logrado hacer algo de trabajo creando CustomRazorBuildProvider que anula el estándar:

public class CustomRazorBuildProvider : RazorBuildProvider
{
  public override void GenerateCode(System.Web.Compilation.AssemblyBuilder assemblyBuilder)
  {
    Assembly a = Assembly.LoadFrom(Path.Combine(HttpRuntime.BinDirectory, "Plugins", "Module1.Data.dll"));
    assemblyBuilder.AddAssemblyReference(a);      
    base.GenerateCode(assemblyBuilder);
  }
} 

pero el inconveniente de esta solución es que cada vez que se compila la vista, se deben agregar referencias a todos los ensamblados en la carpeta Complementos, lo que puede causar problemas de rendimiento más adelante cuando se utilicen muchos complementos.

¿Alguna solución mejor?