MEF e MVC 3 - como carregar visualizações incorporadas dinamicamente do contêiner me

Estou construindo um aplicativo MVC 3 onde o MEF é usado. A idéia principal é ter um mecanismo de plug-in no qual modelos, controladores e visualizações são carregados dinamicamente durante o tempo de execução do contêiner me

ada plugin / módulo consiste em dois conjuntos:

Module1.Data.dll (contém definições de modelo Module1.Web.dll (contém controladores e visualizações)

e são colocados no diretório Plugins na lixeira do aplicativo da 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 ...

ambém existe um módulo principal referenciado por todos os outros módulos: ModuleCore.Data.dll e respectivamente ModuleCore.Web.dl

Então, no Global.asax, o contêiner é compilado da seguinte maneira:

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 é criado, registrado e usado parafinding views na montagem do módulo:

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

controller factory para carregar controladores do contêiner:

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

e também provedor de caminho virtual personalizado para obter montagens do contêiner:

HostingEnvironment.RegisterVirtualPathProvider(new ModuleVirtualPathProvider());

Ok, então toda a infraestrutura para lidar com modelos, controladores e visualizações conectáveis está pronta. Agora tudo funciona ... exceto uma coisa - visualizações fortemente digitadas.

ara ilustrar o problema com mais detalhes, vamos preparar a cen

modelo @UserDTO está localizado em Module1.Data.dll ShowUserController.cs está localizado em Module1.Web.dll / Controllers / Index.cshtml está localizado em Module1.Web.dll / Views / ShowUser (com @model Module1.Data.UserDto)

Agora fazemos o seguinte:

Execute o aplicativo e vá para HOST / ShowUser / Index (o método de ação Index é executado no ShowUserController e a visualização Index.cshtml é buscada)Depois que a visualização Index.cshtml é buscada - a compilação inicia (por RazorBuildProvider) As exceções são lançadas: "não é possível encontrar o tipo de dados no espaço para nome Module1"; em outras palavras, não foi possível encontrar o UserDTO durante a construção dinâmica da exibição

Parece que o compilador / construtor não procurou na Module / Data.dll a pasta bin / Plugins, porque quando eu copiei esse arquivo na pasta bin - ele estava be

Pergunta / problema: por que o construtor não procurou na pasta bin / Plugins, embora esse diretório tenha sido adicionado pelo método AppDomain.CurrentDomain.AppendPrivatePath? Como adicionar caminhos particulares para o construtor de montagem uma vez, para que a pasta de plugins seja levada em consideração

Eu consegui resolver isso criando CustomRazorBuildProvider que substitui o padrão:

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);
  }
} 

mas a desvantagem desta solução é que sempre que a exibição é compilada, é necessário adicionar referências a todos os assemblies na pasta Plugins, o que pode causar problemas de desempenho posteriormente, quando muitos plug-ins serão usado

Qualquer solução melho

questionAnswers(1)

yourAnswerToTheQuestion