using Dpz.Core.Service.Mediator.Features.Account.Internal;

namespace Dpz.Core.Service.Mediator.Features.Account.Queries;

public class GetUserInfoHandler(
    IMapper mapper,
    IRepository<User> userRepository,
    IRepository<UserExtendedInfo> userExtendedInfoRepository
) : IRequestHandler<GetUserInfoRequest, VmUserInfo?>
{
    public async ValueTask<VmUserInfo?> Handle(
        GetUserInfoRequest request,
        CancellationToken cancellationToken
    )
    {
        if (string.IsNullOrWhiteSpace(request.Account) && string.IsNullOrWhiteSpace(request.Name))
        {
            return null;
        }

        User? user = null;
        if (!string.IsNullOrWhiteSpace(request.Account))
        {
            user = await AccountRepositoryHelper.GetUserAsync(
                userRepository,
                request.Account,
                cancellationToken
            );
        }
        else if (!string.IsNullOrWhiteSpace(request.Name))
        {
            user = await userRepository
                .SearchFor(x => x.Name == request.Name)
                .SingleOrDefaultAsync(cancellationToken: cancellationToken);
        }

        if (user == null)
        {
            return null;
        }
        var userInfo = mapper.Map<VmUserInfo>(user.GetUserInfo());

        var extendedInfo = await userExtendedInfoRepository
            .SearchFor(x => x.Id == userInfo.Id)
            .SingleOrDefaultAsync(cancellationToken: cancellationToken);
        userInfo.Email = extendedInfo?.Email ?? "";
        userInfo.EmailVerified = extendedInfo?.EmailVerified ?? false;
        // 从DB获取用户信息是没有SessionId的
        // SessionId 从这里初始化
        userInfo.SessionId = Guid.NewGuid().ToString("N");
        return userInfo;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个基于 CQRS(命令查询职责分离)模式的查询处理器(Query Handler),用于获取用户信息。

类结构

public class GetUserInfoHandler : IRequestHandler<GetUserInfoRequest, VmUserInfo?>
  • 实现了 IRequestHandler 接口,处理 GetUserInfoRequest 请求并返回 VmUserInfo? 类型的结果
  • 使用主构造函数(C# 12 特性)注入三个依赖:
    • IMapper: AutoMapper 对象映射器
    • IRepository<User>: 用户仓储
    • IRepository<UserExtendedInfo>: 用户扩展信息仓储

核心逻辑流程

1. 输入验证

if (string.IsNullOrWhiteSpace(request.Account) && string.IsNullOrWhiteSpace(request.Name))
{
    return null;
}

如果账号(Account)和姓名(Name)都为空,直接返回 null

2. 查询用户

支持两种查询方式:

方式一:通过账号查询(优先)

user = await AccountRepositoryHelper.GetUserAsync(
    userRepository,
    request.Account,
    cancellationToken
);

方式二:通过姓名查询

user = await userRepository
    .SearchFor(x => x.Name == request.Name)
    .SingleOrDefaultAsync(cancellationToken: cancellationToken);

3. 映射基础用户信息

var userInfo = mapper.Map<VmUserInfo>(user.GetUserInfo());

使用 AutoMapper 将用户实体转换为视图模型。

4. 补充扩展信息

var extendedInfo = await userExtendedInfoRepository
    .SearchFor(x => x.Id == userInfo.Id)
    .SingleOrDefaultAsync(cancellationToken: cancellationToken);
    
userInfo.Email = extendedInfo?.Email ?? "";
userInfo.EmailVerified = extendedInfo?.EmailVerified ?? false;

从扩展信息表中获取邮箱和邮箱验证状态,如果不存在则使用默认值。

5. 生成会话 ID

userInfo.SessionId = Guid.NewGuid().ToString("N");

注释说明:从数据库获取的用户信息没有 SessionId,这里生成新的会话标识(32位无连字符的 GUID)。

设计特点

异步处理:所有数据库操作使用 async/await
支持取消:传递 CancellationToken 支持操作取消
分层查询:基础信息和扩展信息分表存储
安全防护:多处 null 检查避免空引用异常
职责单一:专注于用户信息查询,符合 CQRS 原则

评论加载中...