【问题标题】:Map a flatten SQL response to an object containing lists of lists with Automapper使用 Automapper 将扁平化 SQL 响应映射到包含列表列表的对象
【发布时间】:2019-01-10 14:33:56
【问题描述】:

我在运行时收到的错误消息是:

找到未映射的成员。查看下面的类型和成员。 添加自定义映射表达式、忽略、添加自定义解析器或修改源/目标类型

对于没有匹配的构造函数,添加一个无参数 ctor,添加可选参数,或映射所有构造函数参数

List'1 -> MobileRoot(目标成员列表) System.Collections.Generic.List'1[[Strata.CS.Jazz.Biz.Dashboard.MobileInfo, Strata.CS.Jazz.Biz, Version=2019.10.0.0, Culture=neutral, PublicKeyToken=null]] -> Strata。 Jazz.Web.Controllers.MobileController+MobileRoot(目标成员列表)

未映射的属性: 用户


从错误消息中我可以看出,AutoMapper 需要知道如何处理在 MobileRoot 中创建的 ForMember 用户,然后将其传播到链中的每个后续列表。谁能告诉我如何使用 AutoMapper 有效地做到这一点?我知道如何通过使用 GroupBy 和 Select 的 Linq 做到这一点,所以我认为 AutoMapper 应该可以做到这一点。


我的查询返回这个类:

public class MobileInfo
{
    public string NameFull { get; set; }
    public string EmailAddress { get; set; }
    public string SolutionName { get; set; }
    public int SortOrder { get; set; }
    public string Name { get; set; }
    public bool IsLegacy { get; set; }
    public string Description { get; set; }
    public string WidgetName { get; set; }
    public int Row { get; set; }
    public int Col { get; set; }
    public int Height { get; set; }
    public int Width { get; set; }
    public string WidgetClassName { get; set; }
    public string  Data { get; set; }
}

我想将 Automapper 与配置文件一起使用,让它返回:

    internal class MobileRoot
    {
        public IEnumerable<MobileUser> Users { get; set; }
    }

    internal class MobileUser
    {
        public string NameFull { get; set; }
        public string EmailAddress { get; set; }
        public IEnumerable<MobileSolution> Solutions { get; set; }
    }

    internal class MobileSolution
    {
        public string Solution { get; set; } // MobileInfo.SolutionName
        public int SortOrder { get; set; }
        public IEnumerable<MobileDashboard> Dashboards { get; set; }
    }

    internal class MobileDashboard
    {
        public string Dashboard { get; set; } // MobileInfo.Name
        public bool IsLegacy { get; set; }
        public string Description { get; set; }
        public IEnumerable<MobileWidget> Widgets { get; set; }
    }

    internal class MobileWidget
    {
        public string Widget { get; set; } // MobileInfo.WidgetName
        public int Row { get; set; }
        public int Col { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
        public string WidgetClassName { get; set; }
        public string Data { get; set; }
    }

到目前为止我定义的配置文件是:

    public class ProfileMobileRoot : Profile
    {
        public ProfileMobileRoot()
        {
            CreateMap<MobileInfo, MobileRoot>();
        }
    }

    public class ProfileMobileUser : Profile
    {
        public ProfileMobileUser()
        {
            CreateMap<MobileInfo, MobileUser>();
        }
    }

    public class ProfileMobileSolution : Profile
    {
        public ProfileMobileSolution()
        {
            CreateMap<MobileInfo, MobileSolution>();
        }
    }

    public class ProfileMobileDashboard : Profile
    {
        public ProfileMobileDashboard()
        {
            CreateMap<MobileInfo, MobileRoot>();
        }
    }

    public class ProfileMobileWidget : Profile
    {
        public ProfileMobileWidget()
        {
            CreateMap<MobileInfo, MobileWidget>();
        }
    }

【问题讨论】:

    标签: c# .net automapper


    【解决方案1】:

    您可以执行以下操作。有点晚了,所以我的解决方案不是那么复杂......但它有效;)

    public class ProfileMobileRoot : Profile
    {
        public ProfileMobileRoot()
        {
            CreateMap<MobileInfo, MobileWidget>()
                .ForMember(x=>x.Name, opt=>opt.MapFrom(x=>x.WidgetName));
            CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileDashboard>>()
                .ConvertUsing<DashboardConverter>();
    
            CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileSolution>>()
                .ConvertUsing<SolutionConverter>();
            CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileUser>>()
                .ConvertUsing<UserConverter>();
    
            CreateMap<IEnumerable<MobileInfo>, MobileRoot>()
                .ForMember(x => x.Users, opt => opt.MapFrom(x => x.ToList()));
        }
    }
    class UserConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileUser>>
    {
        public IEnumerable<MobileUser> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileUser> destination, ResolutionContext context)
        {
            var groups = source.GroupBy(x => new { x.NameFull, x.EmailAddress});
            foreach (var v in groups)
            {
                yield return new MobileUser()
                {
                    EmailAddress = v.Key.EmailAddress,
                    NameFull = v.Key.NameFull,
                    Solutions = context.Mapper.Map<IEnumerable<MobileSolution>>(source.Where(x =>
                        v.Key.NameFull == x.NameFull && v.Key.EmailAddress== x.EmailAddress)).ToList()
                };
            }
        }
    }
    class SolutionConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileSolution>>
    {
        public IEnumerable<MobileSolution> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileSolution> destination, ResolutionContext context)
        {
            var groups = source.GroupBy(x => new { x.SolutionName, x.SortOrder});
            foreach (var v in groups)
            {
                yield return new MobileSolution()
                {
                    Solution = v.Key.SolutionName,
                    SortOrder = v.Key.SortOrder,
                    Dashboards= context.Mapper.Map<IEnumerable<MobileDashboard>>(source.Where(x =>
                        v.Key.SolutionName== x.SolutionName&& v.Key.SortOrder== x.SortOrder)).ToList()
                };
            }
        }
    }
    
    class DashboardConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileDashboard>>
    {
        public IEnumerable<MobileDashboard> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileDashboard> destination, ResolutionContext context)
        {
            var groups = source.GroupBy(x => new {x.Name, x.IsLegacy, x.Description});
            foreach (var v in groups)
            {
                yield return new MobileDashboard()
                {
                    Dashboard = v.Key.Name,
                    Description = v.Key.Description,
                    IsLegacy = v.Key.IsLegacy,
                    Widgets = context.Mapper.Map<IEnumerable<MobileWidget>>(source.Where(x =>
                        v.Key.IsLegacy == x.IsLegacy && v.Key.Name == x.Name && v.Key.Description == x.Description))
                };
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-29
      • 2021-12-01
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多