Automapper: Hydrate int? based on conditions

I have the following code:

[Test] public void ConditionalMapping() { var src = new Sample1 {Age = 1, Number = null}; var dest = new Sample2 {Age = null, Number = 1}; Hydrate(src, dest, false); Assert.That(dest.Age, Is.EqualTo(1)); Assert.That(dest.Number, Is.EqualTo(1)); src = new Sample1 {Age = null, Number = 1}; dest = new Sample2 {Age = 1, Number = null}; Hydrate(src, dest, true); Assert.That(dest.Age, Is.Null); Assert.That(dest.Number, Is.EqualTo(1)); } public void Hydrate(Sample1 src, Sample2 dest, bool allowOverride) { if (!dest.Age.HasValue || allowOverride) dest.Age = src.Age; if (!dest.Number.HasValue || allowOverride) dest.Number = src.Number; } public class Sample1 { public int? Age { get; set; } public int? Number { get; set; } } public class Sample2 { public int? Age { get; set; } public int? Number { get; set; } } 

What basically moisturizes int? if the value is null , if allowOverride = true in which it will hydrate the value without checking the field value.

How do I do this in Automapper?

I know you can use .Condition () as shown here:

Automapper condition ignored

But I could not understand how:

  • Apply int? based logic int? without defining it one by one.
  • Enable allowOverride boolean in Mapper.
0
source share
1 answer

Perhaps I found a potential solution for you - depending on how you want to use the allowOverride flag.

If you want the flag to work the same for all mappings, you can create a TypeConverter as follows

 public class NullableIntConverter : ITypeConverter<int?, int?> { private bool AllowOverrides { get; set;} public NullableIntConverter(bool allowOverrides) { AllowOverrides = allowOverrides; } public int? Convert(ResolutionContext context) { var source = context.SourceValue as int?; var destination = context.DestinationValue as int?; if (destination.HasValue && !AllowOverrides) return destination; else return source; } } 

Initialize it as follows:

 Mapper.CreateMap<Sample1, Sample2>(); Mapper.CreateMap<int?, int?>().ConvertUsing(new NullableIntConverter(true)); Mapper.AssertConfigurationIsValid(); 

Now it checks the assignment for the value and redefines it depending on your constructor argument.


OR


If you want to configure it for each mapping, then you can use ValueResolver (note that this code can do with some additional verification):

 public class NullableIntResolver : IValueResolver { public bool AllowOverrides { get; set; } public NullableIntResolver(bool allowOverrides) { AllowOverrides = allowOverrides; } public ResolutionResult Resolve(ResolutionResult source) { // Add validation for source and destination types return source.New( ResolveCore((int?) source.Value, DestinationMemberValue(source.Context)), typeof(int?)); } public int? ResolveCore(int? source, int? destination) { if (destination.HasValue && !AllowOverrides) return destination; else return source; } private int? DestinationMemberValue(ResolutionContext context) { var destObject = context.DestinationValue; var destMemberName = context.MemberName; return (int?) destObject .GetType() .GetProperty(destMemberName) .GetValue(destObject, null); } } 

Then you can initialize your mappings as follows:

 var allowOverrides = true; Mapper.CreateMap<Sample1, Sample2>() .ForMember(dest => dest.Age, opt => opt.ResolveUsing<NullableIntResolver>() .FromMember(src => src.Age) .ConstructedBy(() => new NullableIntResolver(allowOverrides))) .ForMember(dest => dest.Number, opt => opt.ResolveUsing<NullableIntResolver>() .FromMember(src => src.Number) .ConstructedBy(() => new NullableIntResolver(allowOverrides))); Mapper.AssertConfigurationIsValid(); 
0
source

Source: https://habr.com/ru/post/924534/


All Articles