1

Suppose I have 2 classes:

Employee()
{
    int ID;
    string Name;
}

Company()
{
    int ID;
    string Name;
    List<Employee> Employees;
}

Given 2 similar (but not equal) Company objects, I want to map the contents of one into the other, mapping all fields except for the IDs (Company.ID and Employee.ID).

I added an Automapper extension to handle this:

    public static IMappingExpression<TSource, TDestination> IgnoreIDs<TSource, TDestination>(
           this IMappingExpression<TSource, TDestination> expression)
    {
        var sourceType = typeof(TSource);
        foreach (var property in sourceType.GetProperties())
        {
            if (property.Name.Contains("ID"))
                expression.ForMember(property.Name, opt => opt.Ignore());
        }
        return expression;
    }

I call it like so:

Mapper.CreateMap<Company, Company>().IgnoreIDs();
Mapper.CreateMap<Employee, Employee>().IgnoreIDs();
var mappedCompany = Mapper.Map(changedCompany, existingCompany);

This works for all ID properties at Company level (mappedCompany.ID == existingCompany.ID, it ignores changedCompany.ID as expected whilst the other properties change).

But this approach doesn't work for child properties. It always sets any Employee.ID to zero! Even when employee properties on existingCompany and changedCompany both have IDs, it will still set any field name containing "ID" to zero. All other properties are mapped appropriately.

Why is it doing this? It's neither ignoring the property or mapping it, but setting it to default?

(AutoMapper v3.3.1)

FBryant87
  • 4,273
  • 2
  • 44
  • 72
  • I've never used AutoMapper, but your function where you're looping through properties you are only looping through the sourceType. To ignore child elements, I'd think you'd need to loop through child elements of it as well. – Cory Aug 08 '17 at 14:13
  • In the latest version you would use a global ignore. – Lucian Bargaoanu Aug 08 '17 at 14:35
  • The thing is the child elements are still being affected - just not in the expected way (they're being changed to zero rather than ignored). Employee properties are looped through when the second CreateMap is called. – FBryant87 Aug 08 '17 at 14:43
  • 1
    They aren't being changed to zero, they are new instances of Employee. Its what AutoMapper does with nested objects. https://stackoverflow.com/questions/3672447/how-do-you-map-a-dto-to-an-existing-object-instance-with-nested-objects-using-au – ajg Aug 08 '17 at 14:48
  • @ajg Good point - in this case is AutoMapper probably not the way to go, or could the answer in that post in theory be reworked to solve this? – FBryant87 Aug 08 '17 at 15:05

1 Answers1

1

Assuming you want to map the Employee lists using the List order (and they have the same number of ietms) then I think you can do the following

 Mapper.CreateMap<Company, Company>().ForMember(dest => dest.Employees,
            opts => opts.Ignore()).IgnoreIDs();
 Mapper.CreateMap<Employee, Employee>().IgnoreIDs();

 var mappedCompany = Mapper.Map(changedCompany, existingCompany);

 for (int i = 0; i < existingCompany.Employees.Count; i++)
 {
     AutoMapper.Mapper.Map(existingCompany.Employees[i], changedCompany.Employees[i]);
 }
ajg
  • 1,743
  • 12
  • 14
  • Thanks - there's a ton of children to map which is the problem, I might try come up with a similar approach to loop through the properties and go through them all. – FBryant87 Aug 08 '17 at 15:38