问题
I'm attempting to use AutoMapper to merge data from multiple objects, and I'm running into a couple issues that I can't seem to solve.
I have an object like:
public class Parent
{
public string Id { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string Key { get; set; }
public int? Value1 { get; set; }
public int? Value2 { get; set; }
public int? Value3 { get; set; }
public int? Value4 { get; set; }
public int? Value5 { get; set; }
}
Obviously the child properties are not all ints, but most of them are nullable.
I have these objects in two different tiers of my application, so I'm using AutoMapper to convert between them:
{
Mapper.CreateMap<Parent, ParentDTO>();
Mapper.CreateMap<ParentDTO, Parent>();
Mapper.CreateMap<Child, ChildDTO>();
Mapper.CreateMap<ChildDTO, Child>();
}
The conversion works well, and I'm happy with what it does. However, now I have a need to merge multiple objects of the same type. I will have one copy of an object which has most or all of the properties populated, and another copy which only has a few, with the rest being null. I want any non-null properties of the second (partial) object to be mapped to the respective field in the first (already filled out) object. As the accepted answer to this answer states, I should be able to use AutoMapper to do this as well, but it doesn't give any clear examples.
However, when I go to perform the operation, I get an object that is identical to either of the objects, not combined like I want.
{
var bigParent = new Parent
{
Id = "14",
Children = new List<Child>
{
new Child
{
Key = "A",
Value1 = 10,
Value2 = 20,
Value3 = 30,
Value4 = 40,
Value5 = 50
}
}
};
var merge = new Parent
{
Id = "14",
Children = new List<Child>
{
new Child
{
Key = "A",
Value1 = null,
Value2 = null,
Value3 = 100,
Value4 = null,
Value5 = null
}
}
};
var res = Mapper.Map(merge, bigParent);
}
I am expecting Child to have values of 10, 20, 100, 40 and 50. However, depending on if I put merge as source or destination in Mapper.Map I get either null, null, 100, null, null or 10, 20, 30, 40, 50.
Is there a way I can get my expected values? I'm thinking having the List is what is causing the issues, since it won't know how to line up the entities (to determine if they are the same or not). If is answers any questions, I would be able to identify if child records are the same by seeing if one or more properties are the same (in this example, Key).
回答1:
Automapper is capable of this, your mapper needs to be configured as such:
Mapper.Initialize(cfg =>
{
// necessary if you are mapping parent to a parent
cfg.CreateMap<Parent, Parent>()
.ForAllMembers(options =>
{
options.Condition(src => src.DestinationValue == null);
});
// necessary if you are mapping your child to a child
cfg.CreateMap<Child, Child>()
.ForAllMembers(options =>
{
options.Condition(src => src.DestinationValue == null);
});
});
And then your usage as such:
var bigParent = new Parent
{
Id = "14",
Children = new List<Child>
{
new Child
{
Key = "A",
Value1 = 10,
Value2 = 20,
Value3 = 30,
Value4 = 40,
Value5 = 50
}
}
};
var merge = new Parent
{
Id = "14",
Children = new List<Child>
{
new Child
{
Key = "A",
Value1 = null,
Value2 = null,
Value3 = 100,
Value4 = null,
Value5 = null
}
}
};
var bigChild = new Child
{
Key = "A",
Value1 = 10,
Value2 = 20,
Value3 = 30,
Value4 = 40,
Value5 = 50
};
var mergeChild = new Child
{
Key = "A",
Value1 = null,
Value2 = null,
Value3 = 100,
Value4 = null,
Value5 = null
};
Mapper.Map(bigChild, mergeChild);
Debug.Assert(mergeChild.Value3 == 100);
Mapper.Map(bigParent, merge);
Debug.Assert(merge.Children[0].Value3 == 100);
回答2:
If you want to ignore null values in mappings defined in AutoMapper Profile, use:
public class MappingProfile : AutoMapper.Profile
{
public MappingProfile()
{
this.CreateMap<Parent, Parent>()
.ForAllMembers(o => o.Condition((source, destination, member) => member != null));
}
}
来源:https://stackoverflow.com/questions/33018728/using-automapper-to-merge-objects