Category Archives: Absurd

AutoMapper is awesome, but ArgumentNullException on IEnumerable.Select pisses me off.

Let me start this off by saying:
I am way undereducated with AutoMapper. I’m fairly certain there is a more elegant way to accomplish this, but I did it my way for the following reasons:

1) I’m stubborn
2) I don’t want to create ValueResolver classes. I don’t know why exactly, but I prefer to just have maps.
3) I can’t rename any of my classes, nor can I change the structure. I’m stuck with what I have.
4) In my instance, I can’t create a map directly from the source type to the destination type – I need to keep the actual references.

The situation:
I have a large number of classes with one to many relationships. For example, let’s take three simple classes:

public class Person
{
     public IList Addresses { get; set; }
}

public class PersonAddress
{
     public Person Person { get; set; }
     public PhysicalAddress PhysicalAddress { get; set; }
}

public class PhysicalAddress
{
     public string City { get; set; }
}

public class DestinationList
{
     public IList<PhysicalAddress> Cities { get; set; }
}

So, I tried a few different methods, with varying results.

Attempt 1:

public static void CreatePersonAddressMap()
{
     AutoMapper.Mapper.CreateMap()
          .ForMember(dest => dest.Cities,
               config => config.MapFrom(person => person.Addresses.Select(add => add.PhysicalAddress)));
          //Throws null reference exception if person.Addresses is null! OH NOES!
}

Result: ArgumentNullException when person.Addresses is null.

Attempt 2:

public static void CreatePersonAddressMap()
{
     AutoMapper.Mapper.CreateMap()
          .AfterMap((person, dest) =>
          {
               if (person.Addresses != null)
                    dest.Cities = person.Addresses.Select(add => add.PhysicalAddress).ToList();
          });
          //This method works, but it's A) Ugly and B) fails the AssertConfigurationIsValid check.
          //I could add .ForMember(dest => dest.Cities, s=> s.Ignore()), but again that sucks
}

Result: Works for the actual mapping, even when person.Addresses is null. However, fails the AutoMapper.Mapper.AssertConfigurationIsValid check

Attempt 3: I thought for sure this would work; what else could the .Condition method be for?

public static void CreatePersonAddressMap()
{
     AutoMapper.Mapper.CreateMap()
          .ForMember(dest => dest.Cities,
               config =>
               {
                    config.Condition(person => person.Addresses != null);
                    config.MapFrom(
                    person => person.Addresses.Select(add => add.PhysicalAddress));
               });
               //This is the method that I thought would work, but the Condition feature is underdocumented, at
               //least in my undereducated opinion.
}

Result: ArgumentNullException when person.Addresses is null. Grr.

Attempt 4:

public static void CreatePersonAddressMap()
{
     AutoMapper.Mapper.CreateMap()
          .ForMember(dest => dest.Cities,
          config => config.MapFrom(
               person =>
                    person.Addresses == null ? null : person.Addresses.Select(add => add.PhysicalAddress)));
               //This is the method I went with. It's still ugly, but it's (i think) a bit easier to follow, and won't crash
               //the AssertConfigurationIsValid check.
}

Result: It works, doesn’t throw an exception, and correctly projects the desired information. However, I will readily admit that it is quite ugly and would much prefer a better option for the configuration of AutoMapper…. Or some advice on what I’m doing wrong. That works too.

Communication is key

And simplicity is king. If you have a vestigial value in your XML/Web Service/Whatever, you can almost be certain that someone, somewhere will use it wrongly. Especially if they need to use one of those two values to submit to another one of your services.

With that in mind, remember to never, ever send any additional information unless absolutely necessary (and specifically requested with a whole set of use-cases).

Developers and Business Requirements

Developers actually like business requirements, from my experience. It tells us what we need to do, so that we can give you a piece of properly functioning software.

What I don’t like, however, is when we are asked to meetings to provide YOU with the business requirements. It’s kind of backwards. What I really dislike is when I ask you to provide an agenda and some questions to the meetings, and I’m given the response “Sorry, I was just assigned to this and that’s the best I can do” … what does that even mean?