You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#中如何用AutoMapper映射分组统计结果至ViewModel

如何将匿名类型列表映射到StatusDetailsViewModel(AutoMapper或手动方案)

嘿,针对你遇到的这个映射问题,其实有两种实用的解决思路——如果场景简单,直接手动映射反而更高效;如果项目统一用AutoMapper,也可以轻松配置实现自动映射。下面分别拆解:

方案一:手动映射(最直接,无需额外依赖)

你的匿名类型属性和StatusDetailsViewModel的字段完全匹配(StatusCountNo),完全可以在LINQ查询的Select阶段直接创建ViewModel实例,一步到位,省掉后续的映射步骤:

public List<StatusDetailsViewModel> CheckMeetingStatus(long actionId) 
{
    var statusDetails = _igniteDb.myTable
        .Where(a => a.actionId == actionId)
        .GroupBy(a => new { a.Status, a.ElectionGroup })
        .GroupBy(c => new { c.Key.Status})
        .Select(b => new StatusDetailsViewModel 
        { 
            Status = b.Key.Status, 
            CountNo = b.Count()
        })
        .ToList();

    return statusDetails;
}

这种方式代码更简洁,性能也更好,毕竟少了AutoMapper的映射开销,适合这种字段匹配简单的场景。

方案二:用AutoMapper实现自动映射

如果你项目里已经在用AutoMapper,或者需要统一用它处理映射,可以按以下步骤配置:

1. 先装AutoMapper包

确保你的项目已经安装了AutoMapper的NuGet包:

# NuGet包管理器控制台
Install-Package AutoMapper
# 或者用.NET CLI
dotnet add package AutoMapper

2. 配置映射规则

在项目启动时(比如Program.cs或者专门的映射配置类),添加AutoMapper的映射配置。因为匿名类型和ViewModel的属性名完全一致,AutoMapper可以自动识别匹配,不过因为匿名类型是编译时的临时类型,我们可以用显式配置确保稳妥:

// 方式1:直接在Program.cs中配置(.NET 6+)
builder.Services.AddAutoMapper(cfg =>
{
    cfg.CreateMap<object, StatusDetailsViewModel>()
        .ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.GetType().GetProperty("Status").GetValue(src)))
        .ForMember(dest => dest.CountNo, opt => opt.MapFrom(src => src.GetType().GetProperty("CountNo").GetValue(src)));
});

// 方式2:创建单独的Profile配置类(更易维护)
public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<object, StatusDetailsViewModel>()
            .ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.GetType().GetProperty("Status").GetValue(src)))
            .ForMember(dest => dest.CountNo, opt => opt.MapFrom(src => src.GetType().GetProperty("CountNo").GetValue(src)));
    }
}
// 然后在Program.cs中注册:builder.Services.AddAutoMapper(typeof(MappingProfile));

注:如果你的匿名类型在编译时能被AutoMapper直接识别,其实也可以不用显式指定成员映射,AutoMapper会自动匹配同名属性,上面的显式配置是更稳妥的兜底方案。

3. 在你的方法中使用AutoMapper

通过构造函数注入拿到IMapper实例,然后执行映射:

// 先通过构造函数注入IMapper
private readonly IMapper _mapper;

public YourServiceClass(IMapper mapper)
{
    _mapper = mapper;
}

public List<StatusDetailsViewModel> CheckMeetingStatus(long actionId) 
{
    var statuses = _igniteDb.myTable
        .Where(a => a.actionId == actionId)
        .GroupBy(a => new { a.Status, a.ElectionGroup })
        .GroupBy(c => new { c.Key.Status})
        .Select(b => new { Status = b.Key.Status, CountNo = b.Count()})
        .ToList();

    // 用AutoMapper把匿名类型列表转成ViewModel列表
    var statusDetails = _mapper.Map<List<StatusDetailsViewModel>>(statuses);

    return statusDetails;
}

小提示

  • 映射时要确保匿名类型的属性名和ViewModel的属性名完全一致(大小写敏感),AutoMapper才能正确匹配。
  • 推荐用依赖注入来管理IMapper实例,不要手动创建,这样可以统一维护映射配置,也更符合.NET的最佳实践。

内容的提问来源于stack exchange,提问作者xzk

火山引擎 最新活动