// Create an environment-agnostic abstraction that provides *only* what we really need.
public interface IUserContext
{
string Username { get; }
}
// Register an environment-specific implementation that encapsulates all the messy details.
public sealed class AspNetUserContext : IUserContext
{
private readonly IHttpContextAccessor accessor;
public AspNetUserContext(IHttpContextAccessor accessor)
{
this.accessor = accessor;
}
public string Username => accessor.HttpContext.Context.User.Identity.Name;
}
public sealed class CustomerRepository : ICustomerRepository
{
private readonly IUserContext userContext;
private readonly IUnitOfWork uow;
// Inject our envorinoment-specific abstraction.
public CustomerRepository(IUserContext userContext, IUnitOfWork uow)
{
this.userContext = userContext;
this.uow = uow;
}
public void Save(Customer entity)
{
// Now, we've isolated ourselves from the underlying framework, allowing our
// code to be run from a Windows service, a console application, etc.
// Further, we've eliminated the trainwreck above, so our class becomes much more
// straightforward to test.
entity.CreatedBy = userContext.Username;
uow.Save(entity);
}
}