AutoMapper - 使用相同的源对象和目标对象类型进行映射

20
我正在使用Automapper来将两个相同类型的对象进行映射,并将任何已更改的新值映射到目标对象。我尝试使用下面的代码,但是它一直报错,而且我甚至不确定是否能够使用Automapper实现这个功能。 例如:
Mapper.CreateMap<UserDetails, UserDetails>();
UserDetails userDetails = Mapper.Map<UserDetails, UserDetails>(userDetailsCurrent, userDetailsNew);
基本上,我需要将来自新对象userDetailsNew的任何新值复制到现有对象userDetailsCurrent中 - 即使它们是相同类型的。这样,我就可以使用新值“更新”现有对象。我这样做的原因是因为我不确定将传递哪些用户详细信息 - 我需要在它们到达时进行映射。 我通常使用Automapper来映射具有相似属性的不同对象 - 但我认为我可以利用Automapper的强大功能以这种方式实现相同的效果。甚至可能有更好的解决方案 - 欢迎任何帮助!

Mapper.Map 应该返回 UserDetails 还是 UserSession - Chris Farmer
它应该返回UserDetails - 我刚刚更新了代码示例。 - Deano
抛出了什么错误? - Carl G
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
13
这是 Automapper 的一个已知行为(查看问题)。你实际上需要告诉 Automapper:
CreateMap<A,A>();
CreateMap<B,B>();
CreateMap<C,C>();

10

这对我来说似乎有效。我的自定义类型:

class MyType
{
    public int MyInt { get; set; }
    public string MyString { get; set; }
}

我的映射代码:

Mapper.CreateMap<MyType, MyType>();
var source = new MyType() {MyInt = 1, MyString = "Hello world"};
var dest = Mapper.Map<MyType, MyType>(source);

除了简单的属性之外,你的自定义类型还有哪些有趣之处?


这看起来不错 - 我离我的电脑有点远,所以我会检查一下并尽快回复! - Deano
有没有不使用 ForMember() 的方法来做到这一点?对于对象的每个属性都这样做可能会更清晰。 - Deano
是的,如果你不使用 ForMember,它仍然可以工作。我只是习惯了使用它们,所以最初包括了它们。 - Chris Farmer
1
快到了,但是否有一种方法可以让我保留目标对象上的现有值。例如 "UserDetails userDetails = Mapper.Map<UserDetails, UserDetails>(userDetailsCurrent, userDetailsNew);" 当我尝试时会抛出错误。我需要保留现有值并映射任何新值。 - Deano

7

可以使用元组和创建一个继承自Automapper的Abstract TypeConverter类的自定义类型转换器来完成此操作。

假设您有一个源类和目标类:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override string ToString()
    {
        return string.Format("Firstname: {0}, Lastname: {1}", FirstName, LastName);
    }
}
然后,您可以构建自定义的转换器类型,如下所示:
public class CustomerPersonConverter : TypeConverter<Tuple<Person, Person>, Person>
{
    protected override Person ConvertCore(Tuple<Person, Person> source)
    {
        var orginalValues = source.Item1;
        var updatedValues = source.Item2;

        var result = new Person
            {
                FirstName = string.IsNullOrEmpty(updatedValues.FirstName) ? orginalValues.FirstName : updatedValues.FirstName,
                LastName = string.IsNullOrEmpty(updatedValues.LastName) ? orginalValues.LastName : updatedValues.LastName
            };

        return result;
    }
}

这可以像这样使用

var orginal = new Person() {FirstName = "Clifford", LastName = "Mayson"};
        var updated = new Person() {FirstName = "Cliff"};

        Mapper.CreateMap<Tuple<Person, Person>, Person>().ConvertUsing<CustomerPersonConverter>();

        var result = Mapper.Map<Person>(new Tuple<Person, Person>(orginal, updated));

        Console.WriteLine(result);

这将导致保留原始的姓氏值(因为更新中缺少了该值),但更新名字值。

Firstname: Cliff, Lastname: Mayson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,