I want to use AutoMapper for mapping DTO s to Models. But my project contains some custom rules for default values for primitive types like [string null value is "_"], [default int value is -1] and [date time fields must be integer like 19990221] etc.
In my test i have a outer DTO which haves Null string values. But my inner system model has a "null string must be represents as a "_" string" rule (its sucks but its a legacy design decision).
Models:
public class OuterDTO
{
public string TestString { get; set; }
}
public class InnerModel
{
public string TestString { get; set; }
}
Automapper type converters:
public class CustomStringToStringConverter : ITypeConverter<string, string>
{
public string Convert(ResolutionContext context)
{
string source = (string)context.SourceValue;
if (source == "_")
return null;
return source;
}
}
public class StringToSafirStringConverter : ITypeConverter<string, string>
{
public string Convert(ResolutionContext context)
{
string source = (string)context.SourceValue;
if (source == null)
return "_";
return source;
}
}
And my Test is :
[TestMethod]
public void StringToSafirStringConverterAndSafirStringToStringConverter_SafirDefaultNullStringAndNullString_ReturnsNullAndSafirNullString()
{
//Arrenge
Mapper.CreateMap<string, string>().ConvertUsing(new StringToSafirStringConverter());//this has to used be DTO To Model map
Mapper.CreateMap<string, string>().ConvertUsing(new SafirStringToStringConverter());//this has to used be Model To DTO map
Mapper.CreateMap<InnerModel, OuterDTO>();
Mapper.CreateMap<OuterDTO, InnerModel>();
Mapper.AssertConfigurationIsValid();
InnerModel expected1 = new InnerModel()
{
TestString = null
};
OuterDTO inner1 = new OuterDTO()
{
TestString = "_"
};
OuterDTO expected2 = new OuterDTO()
{
TestString = "_"
};
InnerModel outer1 = new InnerModel()
{
TestString = null
};
//Act
InnerModel actual1 = Mapper.Map<OuterDTO, InnerModel>(inner1);
OuterDTO actual2 = Mapper.Map<InnerModel, OuterDTO>(outer1);
//Assert
Assert.AreEqual(expected1.TestString, actual1.TestString);
Assert.AreEqual(expected2.TestString, actual2.TestString);
}
Second assert fails.
I have to map DTO s to Models and Models to DTO s hundreds of cases and I have same issue in integer too. How can i choose converters to do different mappings?
You're declaring two mappings from string to string:
Mappings cannot be overwritten, so if you look at the AutoMapper configuration you'll see just one mapping for string to string. (Even if you could define two mappings for string to string, AutoMapper could not know which one to use.)
The way to do this is to define the mapping for the property using ValueResolvers:
Then you write the ValueResolvers, say:
You can then do the same thing for your int and datetime values.