场景
我正在努力遵循 IoC 模式并使用 Microsoft DI Framework,但我碰壁了,无法确定这是我的心态、我的方法,还是我做错了。
我有一个 Multi-Tenancy 应用程序,它利用 Utility 类根据租户的独特配置来处理隔离和访问租户的数据。租户在身份验证期间被识别,但租户数据必须可访问并根据请求进行处理。此 Utility 类在 Startup.cs
中的 ConfigureServices 下注册,构造函数需要两个参数 - TenantDbContext
和 Tenant
。
public class TenantUtility{
public TenantUtility(TenantDbContext context, Tenant tenant){/*...*/}
}
问题
意识到我可能正在挑战 DI 框架的极限,我尝试在 Startup.cs
中构建一个 implementationFactory。我尝试了两种访问租户 ID 以构建 Tenant
对象的方法:一种是使用 User Claim,第二种是 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
属性为空。
我是否错误地接近了模式?在 Utility 类传递到 Controller 之前,我是否应该能够使用 DI 将这种详细程度注入(inject)到 Utility 中?
最佳答案
您不应将非 DI 托管类型传递到您希望容器为您提供的服务(在本例中为您的 Tenant 参数)。只请求容器可以提供的服务。如果您需要一个租户,也许可以注入(inject)另一个服务,如 ITenantAccessor,并且能够获得一个。
我怀疑您的实现可以在中间件中完成(如果不使用 MVC)或作为过滤器(如果使用 MVC)。在任何一种情况下,您都可以使用来自过滤器或中间件类的 DI 来注入(inject)您的租户服务。在类的 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
关于c# - ASP.Net Core 依赖注入(inject) |如何在创建时访问用户或路由数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42490614/