Да, единственная проблема, которую я вижу с решением @Chris Prat, заключается в том, что теперь вам нужно ссылаться на сборки Asp.Net.Core в проектах, которые на самом деле не имеют к этому никакого отношения.Для меня лучшим решением было бы определить новый класс, который имеет требуемые свойства, которые вы хотите.Затем используйте DI / IOC, чтобы зарегистрировать его как Func и передать его в DBContext.то есть.
public class UserInfo
{
public Guid UserId{get;set;}
public string UserName{get;set;
}
, затем в Startup.cs сделайте что-то вроде этого:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
... services registration part ommited
var builder = new ContainerBuilder();
builder.Populate(services);
builder.Register(context=>
{
var identityUser = context.Resolve<IHttpContextAccessor>()?.HttpContext?.User;
var userInfo = new UserInfo()
{
Name=//get it from identityUser.Claims
Id= //get it from identityUser.Claims
}
return userInfo;
}).AsSelf()
.InstancePerLifetimeScope();
}
Затем в DbContext у вас есть это (здесь я использую контейнер IOC Autofac, но любой контейнер, которыйможет зарегистрировать фабрики, может сделать это как StructureMap, Ninject, Autofac ...):
public class MyDbContext: DbContext
{
private readonly Func<UserInfo> _userInfoFactory;
private UserInfo UserInfo => _userInfoFactory();
public MyDbContext(DbContextOptions options, Func<UserInfo> userInfoFactory) : base(options)
{
this._userInfoFactory = userInfoFactory;
}
public void SomeMethod()
{
var someEntity = new SomeEntity()
{
ChangedByUserId = this.UserInfo.Id
...
}
}
}
Это более чистое решение, которое приводит к большей развязке между проектами.