Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用于分组数据的自动映射配置_C#_Api_Automapper - Fatal编程技术网

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;
    }
}