HttpContextAccessor
использует скрытое свойство stati c AsyncLocal<T>
, что означает, что любая реализация HttpContextAccessor
будет обращаться к одним и тем же данным. Это означает, что вы можете просто сделать следующее:
services.AddSingleton(c => new ContextUser(new HttpContextAccessor(), ctxUser));
// Don't forget to call this; otherwise the HttpContext property will be
// null on production.
services.AddHttpContextAccessor();
Если вы обнаружите, что это слишком неявно, или если реализация HttpContextAccessor
не сломается в будущем, вы также можете сделать следующее:
var accessor = new HttpContextAccessor();
services.AddSingleton<IHttpContextAccessor>(accessor);
services.AddSingleton(c => new ContextUser(accessor, ctxUser));
Или вы можете «вытащить» зарегистрированный экземпляр из класса ServiceCollection
:
services.AddHttpContextAccessor();
var accessor = (IHttpContextAccessor)services.Last(
s => s.ServiceType == typeof(IHttpContextAccessor)).ImplementationInstance;
services.AddSingleton(c => new ContextUser(accessor, ctxUser));
Однако я считаю более приятным решение, особенно с точки зрения дизайна, разделить класс ContextUser
; в настоящее время он, кажется, реализует два разных решения. Вы можете разделить их:
public sealed class HttpContextContextUser : IContextUser
{
private readonly IHttpContextAccessor accessor;
public HttpContextContextUser(IHttpContextAccessor accessor) =>
this.accessor = accessor ?? throw new ArgumentNullException("accessor");
public string ContextUserId => this.accessor.HttpContext.User.Identity.Name;
}
public sealed class FixedContextUser : IContextUser
{
public FixedContextUser(string userId) =>
this.ContextUserId = userId ?? throw new ArgumentNullException("userId");
public string ContextUserId { get; }
}
Теперь, в зависимости от среды, в которой вы работаете, вы регистрируете любой из них:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
if (this.Configuration.IsProduction())
{
services.AddSingleton<IContextUser, HttpContextContextUser>();
}
else
{
string ctxUser = Configuration["Data:ConnectedUser"];
services.AddSingleton<IContextUser>(new FixedContextUser(ctxUser));
}
}