11

MEFが使用されているMVC 3アプリケーションを構築しています。主なアイデアは、モデル、コントローラ、およびビューが実行時に動的に読み込まれるプラグインメカニズムをmefコンテナから取得することです。MEFとMVC 3 - 埋め込みビューをmefコンテナから動的にロードする方法は?

各プラグイン/モジュールは、2つのアセンブリからなる:

  • Module1.Data.dll(モデルの定義を含む)
  • Module1.Web.dll(コントローラとビューを含む)

Webアプリケーションのビン内のPluginsディレクトリに置かれています。

  • WebAppの/ビン/プラグイン/ Module1.Data.dll
  • のWebApp /ビン/プラグイン/ Module1.Web.dll
  • のWebApp /ビン/プラグイン/ Module2.Data.dll
  • のWebApp /ビン/プラグイン/ Module2.Web.dll
  • のWebApp /ビン/プラグイン/ModuleCore.Data.dll
  • WebAppの/ビン/プラグイン/ ModuleCore.Web.dll
  • など...他のすべてのモジュールから参照されているコアモジュールもあり

:ModuleCore.Data。 dllおよびそれぞれModuleCore.Web.dll。

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を作成し、登録モジュールアセンブリにおける見つけるビューために使用される:

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

コントローラ

そして、Global.asaxの中に、容器は、以下のように構築されコンテナからコントローラをロードする工場:

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

とコンテナからのアセンブリを取得するための、カスタム仮想パスプロバイダ:

HostingEnvironment.RegisterVirtualPathProvider(new ModuleVirtualPathProvider()); 

オクラホマので、プラグイン可能なモデルを処理するためのインフラ全体、コントローラとビューが用意されています。今はすべて動作します... 1つを除いて - 厳密に型指定されたビュー

のシーンを用意しましょう、より詳細に問題をilustrateするには:

  • UserDTOモデルは/
  • ShowUserController.csがModule1.Web.dll /コントローラに位置していますModule1.Data.dll
  • に位置しています
  • Index.cshtmlはModule1.Web.dll/Views/ShowUser(@model Module1.Dataと宣言されています)にあります。UserDto)今

我々次の操作を行います。

  1. アプリケーションを実行および/ ShowUser /インデックス(アクションメソッド指数がShowUserController上で実行されているホストと
  2. )Index.cshtmlがフェッチされたビューに移動しますIndex.cshtmlがフェッチされた後 -
  3. 例外がスローされました: "名前空間Module1にデータ型が見つかりません"つまりビューを動的に構築中にUserDTOが見つかりません

コンパイラ/ビルダーは、binフォルダにこのファイルをコピーしたときに、Module1.Data.dllのbin/Pluginsフォルダを見ていないようです。

質問/問題:このディレクトリがAppDomain.CurrentDomain.AppendPrivatePathメソッドで追加されていても、ビルダーがbin/Pluginsフォルダを調べなかったのはなぜですか? アセンブリビルダーのプライベートパスを一度追加して、プラグインフォルダを考慮する方法はありますか?

私は標準のものを上書きしますCustomRazorBuildProviderを作成することによって、周りにいくつかの作業を行うために管理している:

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

が、この解決策の欠点は、毎回ビューがコンパイルされ、プラグインフォルダ内のすべてのアセンブリへの参照がする必要があるということです多くのプラグインが使用されると、後でパフォーマンスの問題が発生する可能性があります。

もっと良い解決法はありますか?

+2

これは解決されましたか?私は現時点で私のMVCアプリケーションで同じ問題を解決しようとしています。あなたは私が見ているかもしれない実行しているソースがありますか? – Coppermill

+1

はい、上記のようにCustomRazorBuildProviderで解決しました。その時からHovewer、私たちのアプリケーションはより多くの剃刀のビューが使用され、より純粋なhtml/javascriptのビューが構築されているMVVMのアプローチになってきています。 – untoldex

答えて

1

ここに考えがあります。

View Model Patternに従うと、DTOを直接ビューに送信する代わりに、Viewと同じアセンブリに配置されているViewModelを使用します。

ので、代わりの:

UserDTOモデルはModule1.Data.dllに位置しています ShowUserController.csがModule1.Web.dll /コントローラに位置しています/ Index.cshtmlは/ Module1.Web.dllに位置しています(Module1.Data.UserDto @model宣言付き)ビュー/ ShowUser

あなたは持っているでしょう:

UserDTOモデルは ShowUserController.csがModule1.Web.dll /コントローラに位置していますModule1.Data.dllに位置しています/ Module1.Web.dにあるUserVM LL /のviewmodels Index.cshtmlは

はのviewmodels

AutoMapperを参照してくださいにコントローラー地図あなたのDTOのを持っている(Module1.Web.ViewModels.UserVM @model宣言付き)Module1.Web.dll /ビュー/ ShowUserに位置していますマッピングを手助けする

関連する問題