C#:如何通过接口统一更新模型中的通用字段
基于接口实现通用UserId字段填充(避免代码重复)
1. 定义通用标识接口
先创建一个包含UserId字段的接口,让所有需要该字段的模型类统一实现此接口,规范字段定义:
public interface IHasUserId { Guid UserId { get; set; } }
然后修改你的模型类,实现这个接口:
// 示例订单模型 public class Order : IHasUserId { public int Id { get; set; } public string OrderNumber { get; set; } // 实现接口的通用字段 public Guid UserId { get; set; } }
2. 编写通用填充逻辑
封装一个通用处理类,把UserId的填充逻辑集中实现,无需为每个模型单独写重复代码:
public class UserIdHandler { // 根据项目实际认证方式获取当前用户ID(示例:从HttpContext的Claims中读取) private Guid GetCurrentUserId() { // 实际项目替换为你的认证逻辑,比如: // var userIdClaim = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier); // return Guid.Parse(userIdClaim.Value); return Guid.NewGuid(); // 测试用占位符 } // 单个模型填充方法 public void AssignUserId(IHasUserId model) { if (model == null) throw new ArgumentNullException(nameof(model)); model.UserId = GetCurrentUserId(); } // 批量模型填充方法(可选) public void AssignUserIdToBatch(IEnumerable<IHasUserId> models) { if (models == null) throw new ArgumentNullException(nameof(models)); var currentUserId = GetCurrentUserId(); foreach (var model in models) { model.UserId = currentUserId; } } }
3. 业务代码中调用通用方法
在需要填充UserId的场景,直接调用通用方法即可,实现代码复用:
// 可通过依赖注入管理UserIdHandler实例 var userIdHandler = new UserIdHandler(); // 单个模型填充 var newOrder = new Order(); userIdHandler.AssignUserId(newOrder); // 批量填充多个模型 var modelList = new List<IHasUserId> { new Order(), new UserProfile() }; userIdHandler.AssignUserIdToBatch(modelList);
进阶:结合ORM自动填充(以EF Core为例)
如果使用EF Core,可以通过拦截器实现SaveChanges时自动填充,无需手动调用方法:
public class UserIdSaveInterceptor : SaveChangesInterceptor { private readonly IHttpContextAccessor _httpContextAccessor; public UserIdSaveInterceptor(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public override ValueTask<InterceptionResult<int>> SavingChangesAsync( DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default) { var currentUserId = GetCurrentUserId(); // 遍历所有实现IHasUserId的实体,新增时自动赋值 foreach (var entry in eventData.Context.ChangeTracker.Entries<IHasUserId>()) { if (entry.State == EntityState.Added) { entry.Entity.UserId = currentUserId; } // 若需要更新时也重置UserId,可添加EntityState.Modified的判断 } return base.SavingChangesAsync(eventData, result, cancellationToken); } private Guid GetCurrentUserId() { var userIdClaim = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier); if (userIdClaim == null || !Guid.TryParse(userIdClaim.Value, out var userId)) { throw new InvalidOperationException("无法获取当前用户ID"); } return userId; } }
然后在DbContext配置中注册拦截器:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.AddInterceptors(new UserIdSaveInterceptor(new HttpContextAccessor())); }
这样在调用SaveChanges或SaveChangesAsync时,所有新增的IHasUserId实体都会自动填充UserId,彻底消除重复代码。
内容的提问来源于stack exchange,提问作者Denys
相关产品推荐
相关产品推荐

