C# 用于分组数据的自动映射配置
我有以下型号 资料来源:C# 用于分组数据的自动映射配置,c#,api,automapper,C#,Api,Automapper,我有以下型号 资料来源: public class Opportunity { public Guid Id { get; set; } public string Name { get; set; } public Guid QuotationId { get; set; } public int? QuotationNumber { get; set; } public int? QuotationVersionNumber { get; set; }
public class Opportunity
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid QuotationId { get; set; }
public int? QuotationNumber { get; set; }
public int? QuotationVersionNumber { get; set; }
}
目标:
public class OpportunityDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<QuotationDto> Quotations { get; set; }
}
public class QuotationDto
{
public Guid Id { get; set; }
public int Number { get; set; }
public int VersionNumber { get; set; }
}
public class opportunity to
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
公共列表引用{get;set;}
}
公共类报价
{
公共Guid Id{get;set;}
公共整数{get;set;}
public int VersionNumber{get;set;}
}
我将从数据库中获取的数据与Opportunity模型一样平坦,我的api将OpportunityDto模型公开。
因此,在我的自动映射器配置中,我有以下代码:
services
.AddSingleton(new MapperConfiguration(cfg =>
{
cfg.CreateMap<OpportunityDto, Opportunity>().ReverseMap();
cfg.CreateMap<QuotationDto, Quotation>().ReverseMap();
}).CreateMapper())
服务
.AddSingleton(新的MapperConfiguration(cfg=>
{
CreateMap().ReverseMap();
CreateMap().ReverseMap();
}).CreateMapper())
我想要实现的是一个独特机会的列表,每个机会都有一个嵌套成员,其中包含报价列表。
如何使自动映射器执行此分组?现在,从api返回的opportunityDto的成员总是空的 自动映射配置
您可以执行以下操作:
public static void InitialiseMapper()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<IEnumerable<Opportunity>, OpportunityDto>()
.ForMember(x => x.Id, x => x.MapFrom(y => y.FirstOrDefault().Id))
.ForMember(x => x.Name, x => x.MapFrom(y => y.FirstOrDefault().Name))
.ForMember(x => x.Quotations,
x => x.MapFrom(y => Mapper.Map<IEnumerable<Opportunity>, IEnumerable<QuotationDto>>(y).ToArray()))
;
cfg.CreateMap<Opportunity, QuotationDto>()
.ForMember(x => x.Id, x => x.MapFrom(y => y.QuotationId))
.ForMember(x => x.Number, x => x.MapFrom(y => y.QuotationNumber))
.ForMember(x => x.VersionNumber, x => x.MapFrom(y => y.QuotationVersionNumber))
;
});
}
@阿弗拉特斯,我会给你一个想法,你可以跟随。我假设您使用的是基于服务变量的AspNetCore 您可以创建这样的扩展方法,以便以后调用您的配置服务,如
服务。RegisterMappingsWithAutomapper()
:
现在您需要实现概要文件,在本例中是MyCustomProfile
public class ModelProfile : Profile
{
public ModelProfile()
{
//put your source and destination here
CreateMap<MySource, MyDestination>()
.ConvertUsing<MySourceToMyDestination<MySource, MyDestination>>();
}
}
公共类模型概要文件:概要文件
{
公共模型配置文件()
{
//把你的来源和目的地放在这里
CreateMap()
.ConvertUsing();
}
}
然后您需要实现MySourceToMyDestination类。
下面是我在项目中如何使用它的代码示例
public class ApplicationModel2ApplicationDto : ITypeConverter<ApplicationModel, ApplicationDto>
{
public ApplicationDto Convert(ApplicationModel source, ApplicationDto destination, ResolutionContext context)
{
var mapper = context.Mapper;
try
{
destination = new ApplicationDto
{
ApplicationId = source.ApplicationId,
ApplicationName = source.ApplicationName,
Documents = mapper.Map<IEnumerable<DocumentDto>>(source.Documents),
Tags = mapper.Map<IEnumerable<TagInfoDto>>(source.TagInfos)
};
}
catch
{
return null;
}
return destination;
}
}
公共类应用程序Model12ApplicationTo:ITypeConverter
{
要转换的公共应用程序(应用程序模型源、应用程序目标、ResolutionContext上下文)
{
var mapper=context.mapper;
尝试
{
目的地=新应用程序到
{
ApplicationId=source.ApplicationId,
ApplicationName=source.ApplicationName,
Documents=mapper.Map(source.Documents),
Tags=mapper.Map(source.TagInfos)
};
}
接住
{
返回null;
}
返回目的地;
}
}
希望这有帮助我会亲自手动执行一个
GroupBy
LINQ调用,然后将每个列表的第一个对象映射到OpportunityDto
,然后将每个组列表映射到QuotationDto
。抱歉即将离开,因此没有时间提供完整的解决方案感谢@MichalCiechan的回复。我想我也会这么做,但如果automapper也能支持此自定义映射,那就太棒了。您可以使用自定义映射潜在地添加一个从IEnumerable
到OpportunityDto
的自定义映射,因此,我们可以重新使用该逻辑。@MichalCiechan我试图使其与IEnumerable to OpportunityDto映射一起工作,但失败了
public static IServiceCollection RegisterMappingsWithAutomapper(this IServiceCollection services)
{
var mapperConfig = AutoMapperHelper.InitializeAutoMapper();
services.AddScoped<IMapper>(provider => new Mapper(mapperConfig));
return services;
}
public static class AutoMapperHelper
{
public static MapperConfiguration InitializeAutoMapper()
{
//Load here all your assemblies
var allClasses = AllClasses.FromLoadedAssemblies();
MapperConfiguration config = new MapperConfiguration(cfg =>
{
if (allClasses != null)
{
//here normally I add another Profiles that I use with reflection, marking my DTOs with an interface
cfg.AddProfile(new MappingModelsAndDtos(allClasses));
cfg.AddProfile(new MyCustomProfile());
}
});
return config;
}
}
public class ModelProfile : Profile
{
public ModelProfile()
{
//put your source and destination here
CreateMap<MySource, MyDestination>()
.ConvertUsing<MySourceToMyDestination<MySource, MyDestination>>();
}
}
public class ApplicationModel2ApplicationDto : ITypeConverter<ApplicationModel, ApplicationDto>
{
public ApplicationDto Convert(ApplicationModel source, ApplicationDto destination, ResolutionContext context)
{
var mapper = context.Mapper;
try
{
destination = new ApplicationDto
{
ApplicationId = source.ApplicationId,
ApplicationName = source.ApplicationName,
Documents = mapper.Map<IEnumerable<DocumentDto>>(source.Documents),
Tags = mapper.Map<IEnumerable<TagInfoDto>>(source.TagInfos)
};
}
catch
{
return null;
}
return destination;
}
}