我正在多租户ASP.NET MVC应用程序中实现StructureMap,以注入基于ITenantContext
接口检索数据的租户存储库的实例。有问题的Tenant
是由基本控制器的 RouteData
中的OnActionExecuting
确定的。
如何告诉StructureMap构建TenantContext(tenantID);
,其中tenantID是从我的RouteData
或某个基本控制器属性派生的?
考虑以下路线:
{tenant}/{controller}/{action}/{id}
我的基本控制器根据{tenant} URL参数检索并存储正确的Tenant
。使用Tenant
,可以构建具有ITenantContext
的存储库,以仅检索与该租户相关的数据。
根据其他DI问题,AbstractFactory
可以成为解决方案吗?
答案 0 :(得分:7)
不要将租户存储在控制器上,因为您发现注册服务无法使用它。创建一个瘦服务,其唯一责任是确定租户标识符。该服务可以直接访问静态和HttpContext。这个类并不需要单元测试 - 它的目的是隔离系统的其余部分,以便其他类可以测试。
如果您希望ITenantContext
成为该服务,它可能类似于:
public class TenantContext : ITenantContext
{
public string GetTenant()
{
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
return routeData.GetRequiredString("tenant");
}
}
现在您的控制器可能只依赖于您的存储库接口,您的存储库实现(任何其他关心的服务)可能依赖于ITenantContext
。控制器不需要了解租户。
答案 1 :(得分:1)
@FreshCode,我不知道您是否直接在控制器中依赖于存储库,或者您的控制器是否依赖于服务,而服务依赖于存储库。但是,当控制器由structuremap实例化时,应该已经实例化了服务或存储库。我们在Begin_Request上确定租户,并使用Inject方法将实例化的上下文注入到structuremap中。这在控制器工厂之前执行,因此当控制器被实例化时,所有它的依赖关系都已经创建。
问候。