Troubleshooting and Debugging C#
Lately I got an easy task: transform some existing data models to new models defined in a third party library.
As agreed in the team, AutoMapper will be used for this job. Quickly, I finished most of them, but got stuck into a very simple one.
The existing model is Period
, which is defined as
And the corresponding data model in the 3rd party library is looking like
As we can see, the fields Start
and End
are exactly same:
- same property names
- same property types
So, the mapping code should be easy and straightforward
Unfortunately, the test failed, with the error messages below:
Error mapping types.Mapping types:
Period -> Period
MyWork.Model.Period -> Library.Model.PeriodType Map configuration:
Period -> Period
MyWork.Model.Period -> Library.Model.PeriodDestination Member:
Library.Model.Period.Void .ctor(Library.Model.FhirDateTime, Library.Model.FhirDateTime).parameter start
WHAT?!
The error message says, it failed at the member Start
. However, it’s such a simple one!
Wait, let’s try to ignore the member Start
and expect it to fail at End
.
CreateMap<MyWork.Model.Period, Library.Model.Period>()
.ForMember(d => d.Start, opt => opt.Ignore());
Unfortunately, it fails again, at the member Start
, with the exactly same error messages!!!
I tried to
- map
Start
explicitly … got same errors! - map
StartElement
manually … got same errors! - ignore all members! Sorry, same errors!
I’ve been driven mad, by such a task, which looks so easy.
Ok, calm down.
I have to read the error messages again. And, found this line:
Destination Member:
Library.Model.Period.Void .ctor(Library.Model.FhirDateTime, Library.Model.FhirDateTime).parameter start
Wait, ctor
is … Constructor!
Saying, it tried to create the object with this constructor,
instead of the one without parameters
and then, it found that the given parameters are strings, but NOT FhirDateTime
SO, IT FAILED.
The solution is simple: just use ConstructUsing
to specify which constructor should be used.
CreateMap<MyWork.Model.Period, Library.Model.Period>()
.ConstructUsing(x => new Library.Model.Period());
Now it works, as expected.
After put up the Pull Request, I checked the official docs of AutoMapper and found the reason: Constructor Mapping
Saying, if parameters of a constructor match the members, the mapped constructor will be used by default.
The doc also mentions how to disable it (see details from the link below).