Mapper not using custom Guid map
In asp.net core app within Configure method of Startup class I have
Mapper.AddMap<Guid, string>(src =>
{
return src.ToString();
});
which doesn't get used when calling Mapper.Map()
response.Items = docs.Select(d => Mapper.Map<DocumentSearchViewResponse>(d));
The corresponding string properties that should be filled with string representation of Guid are empty/null.
Tests:
[Test]
public void ShouldMapGuidToSimpleString()
{
var guid = Guid.NewGuid();
Mapper.AddMap<Guid, string>(src => src.ToString());
Assert.AreEqual(guid.ToString(), Mapper.Map<string>(guid)); // passes
}
[Test]
public void ShouldMapGuidPropsToStringProps()
{
Mapper.AddMap<Guid, string>(src => src.ToString());
var customer = GetCustomer();
var newcustomer = Mapper.Map<CustomerNew>(customer);
Assert.AreEqual(customer.AddressId.ToString(), newcustomer.AddressId); // fails
}
with the following CustomerNew
public class CustomerNew
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime RegDate { get; set; }
public string Prop1 { get; set; }
public string Prop2
{
set
{
FirstName = value;
}
}
public string AddressId { get; set; }
}
when you call Mapper.AddMap<Guid, string> you add a map that will be used only when calling:
Mapper.Map(Guid, string)
instead you are calling Mapper.Map<DocumentSearchViewResponse>
if you need to map from guid to string throughout your application you can create a ValueInjection (https://github.com/omuleanu/ValueInjecter/wiki/custom-injections-examples) that will do that and use it in each map you need, or create one map use it in it, and set that map as the default: https://github.com/omuleanu/ValueInjecter#default-map
yeah I just debugged the MapperInstance code and saw it. However, it kinda makes sense to register such a map application-wide because if I introduce a custom value injection (which I've been doing ever since VI came out) I have to always use it with InjectFrom.
I can see there's an option to change the default injection but again that introduces issues if later on we need another custom mapping for a different type.
Maybe I should add mappings like this one to the DefaultMap?
you have multiple options, you can use your injection only in the maps you need it to be used, or instead of using the default static mapper, you create multiple instance mappers where you can also change the default map and use them instead.
What happens if I have this Guid->string mapping and later on need DateTime->string and so on? How would that look like in the DefaultMap implementation, like this:
Mapper.DefaultMap = (src, resType, tag) =>
{
// this is the source code of default map
var res = Activator.CreateInstance(resType);
res.InjectFrom<GuidToStringValueInjection>(src);
res.InjectFrom<DateTimeToStringValueInjection>(src);
// ...
return res;
};
Doesn't look nice to me, I'd rather have an option to provide an array of value injections to use OR use the maps (which are perfect for that).