问题
我有一个 ASP.NET MVC 3 应用程序,具有插件/模块架构和 Multi-Tenancy 支持。 MEF用于解决依赖关系并加载可插拔部件。
每个模块都由 Controller 、 View 和其他对象组成(实际上它是一个程序集)。模块被加载到租户中。
简单的配置可能如下所示:
租户 1:
- 模块 A,版本 1.0 (ModuleA.dll)
- 模块 B,版本 1.0 (ModuleB.dll)
租户2:
- 模块 B,版本 1.0 (ModuleB.dll)
不同模块、不同版本的Dll分别存储在不同的物理位置。 并且应用程序正在一个 AppDomain 上运行(默认)。
但是,如果我们想要在不同租户使用不同模块版本的情况下进行配置,我们会遇到在不同版本中加载相同程序集的问题。这意味着下面的场景无法完全正常工作,因为在解析 ModuleB 的类型期间,我们遇到了组合不匹配异常(版本 1.0 和 1.5 已加载到 MEF 中,但程序集加载器仅将一个程序集加载到 AppDomain 中)。
租户 1:
- 模块 A,版本 1.0 (ModuleA.dll)
- 模块 B,版本 1.0 (ModuleB.dll)
租户2:
- 模块 A,版本 1.5 (ModuleB.dll)
解决方案?
因此我们提出了一种解决方案,即将不同的租户及其模块/程序集加载到单独的 AppDomain 中。这意味着在我们的示例中,Tenant1 和 Tenant2 已加载到 AppDomain1 和 AppDomain2 中。在 ASP.NET MVC 管道中,我们连接到 Controller 工厂以选择正确的应用程序域,如下所示:
- 请求由默认 AppDomain(Web 应用程序启动的 AppDomain)处理
- Controller 工厂
- 从请求中获取 Tenant_Id 并从正确的 AppDomain 解析正确的 Controller (我们有 Tenant_Id->Tenant->AppDomain 关系)
- 返回ControllerProxy(这是一个实现IController的代理类,并继承MarshalByRefObject以便能够在不同的App Domian之间传递 Controller )
- 从请求中获取 Tenant_Id 并从正确的 AppDomain 解析正确的 Controller (我们有 Tenant_Id->Tenant->AppDomain 关系)
- Action 调用者
- 在 Controller 代理对象上调用正确的操作,并且现在在底层应用程序域中执行
- 在这里我们遇到了问题,因为操作调用者无法将不可序列化的 RequestContext 传递到另一个应用程序域(换句话说,controllerProxy.Execute(RequestContext context) 抛出有关序列化的异常)<
问题:
- 如何以良好的方式在应用域之间传递 RequestContext(不可序列化对象)?
- 是否可以连接到管道中的另一个步骤,以将执行重定向到底层应用程序域(在 Controller 工厂之前?)
- 或者对此问题有其他解决方案的想法吗?
最佳答案
不可能。如果您尝试使用不同的 AppDomain,ASP.NET 将会回来困扰您。
相反,使用基于角色的授权来控制不同模块的访问。
我刚刚写了一篇关于 ASP.NET MVC3 中的插件系统的文章:http://blog.gauffin.org/2012/05/griffin-mvccontrib-the-plugin-system/
关于asp.net-mvc - ASP.NET MVC 应用程序具有插件和 Multi-Tenancy 支持以及单独的 AppDomains?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10328811/