問題
プラグイン/モジュールアーキテクチャとマルチテナンシーサポートを備えたASP.NETMVC3アプリケーションがあります。MEFは、依存関係を解決し、プラグ可能なパーツをロードするために使用されます。
各モジュールは、コントローラー、ビュー、およびその他のオブジェクトで構成されています(物理的には1つのアセンブリです)。モジュールはテナントにロードされます。
単純な構成は次のようになります。
テナント1:
- モジュールA、バージョン1.0(ModuleA.dll)
- モジュールB、バージョン1.0(ModuleB.dll)
テナント2:
- モジュールB、バージョン1.0(ModuleB.dll)
さまざまなモジュールおよびさまざまなバージョンのDLLは、さまざまな物理的な場所に別々に格納されます。また、アプリケーションは1つのAppDomain(デフォルトは1つ)で実行されています。
ただし、異なるテナントが異なるモジュールバージョンを使用する構成を実行する場合、同じアセンブリを異なるバージョンでロードする際に問題が発生します。これは、ModuleBからタイプを解決しているときに、構成の不一致の例外が発生したため、以下のシナリオが完全に機能していないことを意味します(バージョン1.0および1.5がMEFにロードされましたが、アセンブリローダーによってAppDomainにロードされたアセンブリは1つだけです)。
テナント1:
- モジュールA、バージョン1.0(ModuleA.dll)
- モジュールB、バージョン1.0(ModuleB.dll)
テナント2:
- モジュールA、バージョン1.5(ModuleB.dll)
解決?
そこで、さまざまなテナントとそのモジュール/アセンブリを別々のAppDomainにロードするという1つのソリューションを考え出しました。つまり、この例では、Tenant1とTenant2がAppDomain1とAppDomain2にロードされています。ASP.NET MVCパイプラインでは、適切なアプリドメインを選択するために、コントローラーファクトリに接続しました。これは次のようになります。
- リクエストはデフォルトでAppDomain(Webアプリケーションが開始したもの)で処理されます
- コントローラファクトリ
- リクエストからTenant_Idを取得し、適切なAppDomainから適切なコントローラーを解決します(Tenant_Id-> Tenant-> AppDomainの関係があります)
- ControllerProxyを返します(これは、IControllerを実装し、MarshalByRefObjectを継承して、異なるApp Domian間でコントローラーを渡すことができるプロキシクラスです)。
- リクエストからTenant_Idを取得し、適切なAppDomainから適切なコントローラーを解決します(Tenant_Id-> Tenant-> AppDomainの関係があります)
- アクションインボーカー
- コントローラプロキシオブジェクトで適切なアクションが呼び出され、現在、基盤となるアプリドミアンで実行が行われます。
- そして、ここで問題が発生しました。これは、アクションの呼び出し元がシリアル化できないRequestContextを別のアプリドメインに渡すことができないためです(つまり、controllerProxy.Execute(RequestContext context)がシリアル化に関する例外をスローしています)
質問:
- アプリドメイン間でRequestContext(シリアル化不可能なオブジェクト)を適切に渡す方法は?
- パイプラインの別のステップに接続して、実行を基盤となるアプリドメインにリダイレクトすることは可能ですか(コントローラーファクトリの前ですか?)
- または、この問題の別の解決策についてのアイデアはありますか?