This seems like a very simple question, so hopefully this will be easy.
I have a custom string
to bool
map in Automapper that simply converts "Y"
and "N"
to true
and false
. It doesn't get much simpler:
Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");
This works fine in this primitive example:
public class Source
{
public string IsFoo { get; set; }
public string Bar { get; set; }
public string Quux { get; set; }
}
public class Dest
{
public bool IsFoo { get; set; }
public string Bar { get; set; }
public int Quux { get; set; }
}
// ...
Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");
Mapper.CreateMap<Source, Dest>();
Mapper.AssertConfigurationIsValid();
Source s = new Source { IsFoo = "Y", Bar = "Hello World!", Quux = "1" };
Source s2 = new Source { IsFoo = "N", Bar = "Hello Again!", Quux = "2" };
Dest d = Mapper.Map<Source, Dest>(s);
Dest d2 = Mapper.Map<Source, Dest>(s2);
However, let's say instead I want to take the Source
data from a DataReader
:
Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");
Mapper.CreateMap<IDataReader, Dest>();
Mapper.AssertConfigurationIsValid();
DataReader reader = GetSourceData();
List<Dest> mapped = Mapper.Map<IDataReader, List<Dest>>(reader);
For every Dest
in mapped
, the IsFoo
property is true
. What am I missing here?
I ended up ditching the string
to bool
map and instead creating extension methods for IMemberConfigurationExpression<IDataReader>
. Extension methods plural because I also ran into this issue where numerical data coming back from the DB didn't match the destination types perfectly, causing inconsistent large numbers. Since the database stuff was out of my control, I had to force the mapper to read it as a certain type. So here's what I ended up with:
public static class Mapping
{
public static void Init()
{
Mapper.CreateMap<IDataReader, Dest>()
.ForMember(s => s.IsFoo, opt => opt.ReadAsBoolean("IsFoo"))
.ForMember(s => s.Quux, opt => opt.ReadAsNumber("Quux"));
Mapper.AssertConfigurationIsValid();
}
public static void ReadAsBoolean(this IMemberConfigurationExpression<IDataReader> opt, string fieldName)
{
opt.MapFrom(reader => reader.GetString(reader.GetOrdinal(fieldName)).ToUpper() == "Y");
}
public static void ReadAsNumber(this IMemberConfigurationExpression<IDataReader> opt, string fieldName)
{
opt.MapFrom(reader => reader.GetDecimal(reader.GetOrdinal(fieldName)));
}
}
The duplication of the property names as strings goes against my grain, but I suspect someone with more Automapper skills could make that more elegant. For now, this at least works.
Inside the IDataReader
the data is stored as objects and not strings. So I'm assuming AutoMapper
is evaluating anything that is not null as true
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.