ValueInjecter icon indicating copy to clipboard operation
ValueInjecter copied to clipboard

Mapper not using custom Guid map

Open brgrz opened this issue 6 years ago • 5 comments

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.

brgrz avatar Aug 27 '19 11:08 brgrz

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; }
	}

brgrz avatar Aug 27 '19 12:08 brgrz

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

omuleanu avatar Aug 27 '19 12:08 omuleanu

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?

brgrz avatar Aug 27 '19 12:08 brgrz

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.

omuleanu avatar Aug 27 '19 13:08 omuleanu

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).

brgrz avatar Aug 27 '19 13:08 brgrz