脚本
我正在努力遵循ioc模式并使用microsoft di框架,但我遇到了困难,无法决定这是我的思维方式、方法,还是我做错了。
我有一个多租户应用程序,它利用一个实用程序类来处理隔离,并根据租户的独特配置访问其数据。在身份验证期间标识租户,但必须根据请求访问和处理租户数据。这个实用程序类在Startup.cs
中的configureservices下注册,构造函数需要两个参数-aTenantDbContext
和aTenant
。
public class TenantUtility{
public TenantUtility(TenantDbContext context, Tenant tenant){/*...*/}
}
问题
意识到我可能正在突破di框架的限制,我正试图在
Startup.cs
中构建一个实现工厂。我尝试了两种访问租户id来构建Tenant
对象的方法:一种是使用用户声明,另一种是route参数。services.AddTransient<TenantUtility>((svc)=> {
var tenantContext = svc.GetService<TenantDbContext>();
var accessor = svc.GetService<IHttpContextAccessor>();
var httpContext = accessor.HttpContext;
//httpContext is NULL...
//How do I get access to the tenant?
Common.Tenant t = new Common.Tenant();
//Set Tenant Identifier in t (once I get it)
return new StudentDataManager(tenantContext, t);
});
在这两种情况下,当我在startup.cs中设置implementationfactory时,我没有访问用户的权限,也没有访问routedata的权限(或者不知道如何获取它)--我甚至尝试使用
IHttpContextAccessor
,但HttpContext
属性为空。我是不是走错路了?在将实用程序类传递到控制器之前,我是否应该能够使用di将此级别的详细信息注入实用程序?
最佳答案
您不应该将非DI托管类型传入您希望容器为您提供的服务(在本例中,是您的租户参数)。只请求容器可以提供的服务。如果您需要一个租户,也许可以注入另一个服务,比如itenantAccessor,并能够获得一个租户。
我怀疑您的实现可以在中间件中完成(如果不使用mvc)或作为过滤器(如果使用mvc)。在这两种情况下,都可以使用filter或middleware类中的di注入租户服务。在类的invoke方法中,您将有权访问当前上下文和请求,并且应该能够执行所需的操作。请记住,ConfigureServices
在应用程序启动之前运行,因此没有上下文,也没有请求。
如果您想查看一些过滤器的示例,特别是如何将di转换为过滤器,请查看:
https://github.com/ardalis/GettingStartedWithFilters
和
http://ardalis.com/real-world-aspnet-core-mvc-filters
如果您希望在中间件中执行此操作,则这些可能会有所帮助:
https://github.com/ardalis/NotFoundMiddlewareSample
和
http://ardalis.com/using-custom-middleware-to-record-and-fix-404s-in-aspnet-core-apps