有条件地将一种源类型映射到两种目标类型

时间:2016-03-11 19:34:19

标签: c# mapping automapper

我有像这样的源DTO

public class Member 
{
    public string MemberId {get;set;}
    public string MemberType {get;set;}
    public string Name {get;set;}
}

会员类型可以是“人”或“公司”。

还有两个这样的目标类

public class PersonMember 
{
    public int PersonMemberId {get;set;}
    public string Name {get;set;}
}

public class CompanyMember 
{
    public int CompanyMemberId {get;set;}
    public string Name {get;set;}
}

我想使用Automapper来检查MemberType在源类中的值,并根据该类型映射到两种目标类型之一。

我看到了conditionally mapping的示例,但它会映射它执行条件检查的字段。我想检查条件并映射不同的字段。

var config = new MapperConfiguration(cfg => {
  cfg.CreateMap<Foo,Bar>()
    .ForMember(dest => dest.baz, opt => opt.Condition(src => (src.baz >= 0))); 
});

我的目标是这样的 -

cfg.CreateMap<Member, PersonMember>()
.ForMember(dest => PersonMember.PersonMemberId, opt => if the source.MemberType == "Person" perform mapping from MemberId, otherwise do nothing);

cfg.CreateMap<Member, CompanyMember>()
.ForMember(dest => CompanyMember.CompanyMemberId, opt => if the source.MemberType == "Company" perform mapping from MemberId, otherwise do nothing);

4 个答案:

答案 0 :(得分:4)

使用automapper,您必须在调用映射器上指定返回类型,例如。 mapper.Map<PersonMember>(member),这表示返回类型为PersonMember,因此您无法返回CompanyMember

您可以这样做:

var configPerson = new MapperConfiguration(cfg => cfg.CreateMap<Member, PersonMember>());
var configCompany = new MapperConfiguration(cfg => cfg.CreateMap<Member, CompanyMember>());

PersonMember personMember = null;
CompanyMember companyMember = null;

switch (member.MemberType )
{
    case "PersonMember":
        var mapper = configPerson.CreateMapper();
        personMember = mapper.Map<PersonMember>(member);
        break;
    case "CompanyMember":
        var mapper = configCompany.CreateMapper();
        companyMember = mapper.Map<CompanyMember>(member);
        break;
    default:
        throw new Exception("Unknown type");
        break;
}

或者您可以使用object作为返回类型尝试Custom type converters

答案 1 :(得分:2)

介绍一些基类([\"'])(?:(?=(\\?))\2.)*?\1 。从新基类继承>>> print arguments [('"', ''), ('"', '')] Member

然后定义这些映射:

PersonMember

现在您可以使用CompanyMember

进行地图制作

答案 2 :(得分:1)

  

我看到了有条件映射的例子,但它映射了它执行条件检查的字段。我想检查条件并映射不同的字段。

尝试使用这样的配置:

cfg.CreateMap<Member, PersonMember>()
    .ForMember(dest => PersonMember.PersonMemberId, opt => { 
        opt.Condition(src => src.MemberType == "Person");
        opt.MapFrom(src => src.MemberId);
     });
cfg.CreateMap<Member, CompanyMember>()
    .ForMember(dest => CompanyMember.CompanyMemberId, opt => { 
        opt.Condition(src => src.MemberType == "Company");
        opt.MapFrom(src => src.MemberId);
     });

如果您从不兼容的对象Id字段进行映射,则会将其设置为0

答案 3 :(得分:1)

对于版本5及更高版本,您可以尝试以下代码:

using System;
using AutoMapper;

namespace AutoMapOneToMulti
{
    class Program
    {
        static void Main(string[] args)
        {
            RegisterMaps();

            var s = new Source { X = 1, Y = 2 };

            Console.WriteLine(s);
            Console.WriteLine(Mapper.Map<Source, Destination1>(s));
            Console.WriteLine(Mapper.Map<Source, Destination2>(s));

            Console.ReadLine();
        }
        static void RegisterMaps()
        {
            Mapper.Initialize(cfg => cfg.AddProfile<GeneralProfile>());
        }
    }
    public class GeneralProfile : Profile
    {
        public GeneralProfile()
        {
            CreateMap<Source, Destination1>();
            CreateMap<Source, Destination2>();
        }
    }
    public class Source
    {
        public int X { get; set; }

        public int Y { get; set; }

        public override string ToString()
        {
            return string.Format("Source = X : {0}, Y : {1}", X, Y);
        }
    }
    public class Destination1
    {
        public int X { get; set; }

        public int Y { get; set; }
        public override string ToString()
        {
            return string.Format("Destination1 = X : {0}, Y : {1}", X, Y);
        }
    }
    public class Destination2
    {
        public int X { get; set; }

        public int Y { get; set; }
        public override string ToString()
        {
            return string.Format("Destination2 = X : {0}, Y : {1}", X, Y);
        }
    }
}

对于低于5的版本,你可以试试这个:

using System;
using AutoMapper;

namespace AutoMapOneToMulti
{
    class Program
    {
        static void Main(string[] args)
        {
            RegisterMaps();

            var s = new Source { X = 1, Y = 2 };

            Console.WriteLine(s);
            Console.WriteLine(Mapper.Map<Source, Destination1>(s));
            Console.WriteLine(Mapper.Map<Source, Destination2>(s));

            Console.ReadLine();
        }
        static void RegisterMaps()
        {
            Mapper.Initialize(cfg => cfg.AddProfile<GeneralProfile>());
        }
    }
    public class GeneralProfile : Profile
    {
        protected override void Configure()
        {
            CreateMap<Source, Destination1>();
            CreateMap<Source, Destination2>();
        }
    }
    public class Source
    {
        public int X { get; set; }

        public int Y { get; set; }

        public override string ToString()
        {
            return string.Format("Source = X : {0}, Y : {1}", X, Y);
        }
    }
    public class Destination1
    {
        public int X { get; set; }

        public int Y { get; set; }
        public override string ToString()
        {
            return string.Format("Destination1 = X : {0}, Y : {1}", X, Y);
        }
    }
    public class Destination2
    {
        public int X { get; set; }

        public int Y { get; set; }
        public override string ToString()
        {
            return string.Format("Destination2 = X : {0}, Y : {1}", X, Y);
        }
    }
}

如果您想要动态功能,请使用此扩展程序:

public static dynamic DaynamicMap(this Source source)
{
    if (source.X == 1)
        return Mapper.Map<Destination1>(source);
    return Mapper.Map<Destination2>(source);
}

Console.WriteLine(new Source { X = 1, Y = 2 }.DaynamicMap());
Console.WriteLine(new Source { X = 2, Y = 2 }.DaynamicMap());