SignalR:为 IUserIdProvider 使用范围内的服务

SignalR: Use scoped service for IUserIdProvider

我必须进行服务/数据库调用才能根据请求声明映射 UserId。通常,我会像这样简单地做到这一点:

public class AuthUserIdProvider : IUserIdProvider
    {
        private IBusinessDependencies Dependencies { get; }

        public AuthUserIdProvider(IBusinessDependencies dependencies)
        {
            Dependencies = dependencies;
        }

        public string GetUserId(HubConnectionContext connection)
        {
            var email = connection.User.Claims.FirstOrDefault(m => m.Type.Equals(ClaimTypes.Email, StringComparison.OrdinalIgnoreCase))?.Value;

            if (string.IsNullOrEmpty(email))
            {
                return null;
            }

            return Dependencies.EntityServices.UserService.GetUserByEmailCached(email).GetAwaiter().GetResult().Id.ToString();
        }
    }

但是 IBusinessDependencies 是有范围的,因为有一堆业务逻辑取决于特定的请求/会话。

是否可以将 IUserIdProvider 注册为作用域而不是单例?或者也许还有其他更好的解决方案?

我个人从来不需要使用 IUserIdProvider,但我看不到任何特别 要求 它是单例的。不过,我可能错过了一些东西。但是,我想您在来这里之前至少必须尝试将其注册为作用域(希望如此)。

假设它必须是单例,那么你唯一的选择就是 service-locator 模式。不是注入 IBusinessDependencies,而是注入 IServiceProvider。然后每当你真正需要你的 IBusinessDependencies 实例时:

using (var scope = _serviceProvider.CreateScope())
{
    var dependencies = scope.ServiceProvider.GetRequiredService<IBusinessDependencies>();
    // do something with dependencies
}

如果不明显,您不能将 IBusinessDependencies 实例持久化到 ivar 或其他东西。每次需要使用时,您都需要将其从服务集合中拉出。