4

我正在尝试在两个对象列表之间进行映射。源类型具有 type 的复杂属性A;目标类型是类型的扁平子集A加上源类型中的附加标量属性。

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Source
{
    public A MyA { get; set; }
    public int SomeOtherValue { get; set; }
}

public class Destination
{
    public string Name { get; set; }
    public int SomeOtherValue { get; set; }
}

如果不清楚,我想Source.MyA.Name映射到Destination.NameSource.SomeOtherValue映射到Destination.SomeOtherValue.

实际上,typeA有十几个属性,其中 80% 映射到Destination. 如果我像这样明确地拼出映射,我可以让事情正常工作CreateMap

CreateMap<Source, Destination>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.MyA.Name));

这里的缺点是我想避免必须为每个需要复制到的属性添加ForMember一行。我希望我可以做类似的事情:ADestination

CreateMap<Source, Destination>()
    .ForMember(dest => dest, opt => opt.MapFrom(src => src.MyA));

但是,如果我尝试上述操作,则在注册映射时会出现运行时错误:“成员的自定义配置仅支持类型上的顶级个人成员。”

谢谢

4

3 回答 3

5

A在and Destination、 andSource和 and之间创建映射Destination,然后AfterMap()在第二个中使用第一个映射

Mapper.CreateMap<A, Destination>();
Mapper.CreateMap<Source, Destination>()
      .AfterMap((s, d) => Mapper.Map<A, Destination>(s.MyA, d));

然后像这样使用它:

var res = Mapper.Map<Source, Destination>(new Source { SomeOtherValue = 7,  MyA = new A { Id = 1, Name = "SomeName" } });
于 2012-11-01T00:16:13.470 回答
0

As a workaround you can use custom type converter with additional property in the destination type to avoid recursion.

[TestFixture]
public class MapComplexType
{
    [Test]
    public void Map()
    {
        Mapper.CreateMap<A, Destination>();

        Mapper.CreateMap<Source, Destination>().ConvertUsing(new TypeConvertor());
        var source = new Source
                         {
                             MyA = new A
                                       {
                                           Name = "Name"
                                       },
                                       SomeOtherValue = 5
                         };
        var dest = new Destination();
        Mapper.Map(source, dest);
        Assert.AreEqual(dest.Name, "Name");
    }
}

public class TypeConvertor : ITypeConverter<Source, Destination>
{
    public Destination Convert(ResolutionContext context)
    {
        var destination = (Destination) context.DestinationValue;
        if (!((Destination)context.DestinationValue).IsMapped || destination == null)
        {
            destination = destination ?? new Destination();
            destination.IsMapped = true; // To avoid recursion
            Mapper.Map((Source)context.SourceValue, destination);
                            destination.IsMapped = false; // If you want to map the same object few times
        }
        Mapper.Map(((Source)context.SourceValue).MyA, destination);
        return (Destination)context.DestinationValue;
    }
}

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Source
{
    public A MyA { get; set; }
    public int SomeOtherValue { get; set; }
}

public class Destination
{
    public string Name { get; set; }
    public int SomeOtherValue { get; set; }
    // Used only for mapping purposes
    internal bool IsMapped { get; set; }
}
于 2012-10-29T22:21:34.103 回答
0

尝试这个,

Mapper.CreateMap<A, Destination>();
Mapper.CreateMap<Source, Destination>()
    .ForMember(destination => destination.Name, options => options.MapFrom(source => Mapper.Map<A, Destination>(source.MyA).Name));

var objSource = new Source { SomeOtherValue = 7, MyA = new A { Id = 1, Name = "SomeName" } };
var result = Mapper.Map<Source, Destination>(objSource);
于 2012-11-13T05:46:26.850 回答