AutoMapper: How to parse an Int from a String and possible to creating rules based on data type?

后端 未结 3 1385
迷失自我
迷失自我 2020-12-30 01:38

I have two models for my form, a ViewModel going to it, and a ControlModel coming from it. The ControlModel has all the same field names and hierarchy, but all of the field

相关标签:
3条回答
  • 2020-12-30 02:07

    I ended up doing something like this:

    Mapper.CreateMap<string, int>().ConvertUsing<IntTypeConverter>();
    Mapper.CreateMap<string, int?>().ConvertUsing<NullIntTypeConverter>();
    Mapper.CreateMap<string, decimal?>().ConvertUsing<NullDecimalTypeConverter>();
    Mapper.CreateMap<string, decimal>().ConvertUsing<DecimalTypeConverter>();
    Mapper.CreateMap<string, bool?>().ConvertUsing<NullBooleanTypeConverter>();
    Mapper.CreateMap<string, bool>().ConvertUsing<BooleanTypeConverter>();
    Mapper.CreateMap<string, Int64?>().ConvertUsing<NullInt64TypeConverter>();
    Mapper.CreateMap<string, Int64>().ConvertUsing<Int64TypeConverter>();
    Mapper.CreateMap<string, DateTime?>().ConvertUsing<NullDateTimeTypeConverter>();
    Mapper.CreateMap<string, DateTime>().ConvertUsing<DateTimeTypeConverter>();
    
    Mapper.CreateMap<SourceClass, DestClass>();
    
    Mapper.Map(mySourceObject, myDestinationObject);
    

    And the classes it references (first draft):

    // TODO: Boil down to two with Generics if possible
    #region AutoMapTypeConverters
    // Automap type converter definitions for 
    // int, int?, decimal, decimal?, bool, bool?, Int64, Int64?, DateTime
    // Automapper string to int?
    private class NullIntTypeConverter : TypeConverter<string, int?>
    {   protected override int? ConvertCore(string source)
        {   if (source == null)
                return null;
            else
            {   int result;
                return Int32.TryParse(source, out result) ? (int?) result : null;
    }   }   }
    // Automapper string to int
    private class IntTypeConverter : TypeConverter<string, int>
    {   protected override int ConvertCore(string source)
        {   if (source == null)
                throw new MappingException("null string value cannot convert to non-nullable return type.");
            else
                return Int32.Parse(source); 
    }   }
    // Automapper string to decimal?
    private class NullDecimalTypeConverter : TypeConverter<string, decimal?>
    {   protected override decimal? ConvertCore(string source)
        {   if (source == null)
                return null;
            else
            {   decimal result;
                return Decimal.TryParse(source, out result) ? (decimal?) result : null;
    }   }   }
    // Automapper string to decimal
    private class DecimalTypeConverter : TypeConverter<string, decimal>
    {   protected override decimal ConvertCore(string source)
        {   if (source == null)
                throw new MappingException("null string value cannot convert to non-nullable return type.");
            else
                return Decimal.Parse(source); 
    }   }
    // Automapper string to bool?
    private class NullBooleanTypeConverter : TypeConverter<string, bool?>
    {   protected override bool? ConvertCore(string source)
        {   if (source == null)
                return null;
            else
            {   bool result;
                return Boolean.TryParse(source, out result) ? (bool?) result : null;
    }   }   }
    // Automapper string to bool
    private class BooleanTypeConverter : TypeConverter<string, bool>
    {   protected override bool ConvertCore(string source)
        {   if (source == null)
                throw new MappingException("null string value cannot convert to non-nullable return type.");
            else
                return Boolean.Parse(source); 
    }   }
    // Automapper string to Int64?
    private class NullInt64TypeConverter : TypeConverter<string, Int64?>
    {   protected override Int64? ConvertCore(string source)
        {   if (source == null)
                return null;
            else
            {   Int64 result;
                return Int64.TryParse(source, out result) ? (Int64?)result : null;
    }   }   }
    // Automapper string to Int64
    private class Int64TypeConverter : TypeConverter<string, Int64>
    {   protected override Int64 ConvertCore(string source)
        {   if (source == null)
                throw new MappingException("null string value cannot convert to non-nullable return type.");
            else
                return Int64.Parse(source); 
    }   }
    // Automapper string to DateTime?
    // In our case, the datetime will be a JSON2.org datetime
    // Example: "/Date(1288296203190)/"
    private class NullDateTimeTypeConverter : TypeConverter<string, DateTime?>
    {   protected override DateTime? ConvertCore(string source)
        {   if (source == null)
                return null;
            else
            {   DateTime result;
                return DateTime.TryParse(source, out result) ? (DateTime?) result : null;
    }   }   }
    // Automapper string to DateTime
    private class DateTimeTypeConverter : TypeConverter<string, DateTime>
    {   protected override DateTime ConvertCore(string source)
        {   if (source == null)
                throw new MappingException("null string value cannot convert to non-nullable return type.");
            else
                return DateTime.Parse(source); 
    }   }
    #endregion
    
    0 讨论(0)
  • 2020-12-30 02:11

    Just to keep updated.
    Newer versions can do some simple conversions automatically

        public class Source
        {
            public string String{ get; set; }
        }
    
        public class Target
        {
            public int Int { get; set; }
            public decimal Decimal{ get; set; }
        }
    
        [Fact]
        public void TestCustomMap()
        {
            Mapper.Initialize(cfg =>
                cfg.CreateMap<Source, Target>()
                    .ForMember(dest => dest.Int, opt => opt.MapFrom(src => src.String))
                    .ForMember(dest => dest.Decimal, opt => opt.MapFrom(src => src.String)));
    
            var target = Mapper.Instance.Map<Target>(new Source { String = "123" });
            Assert.Equal(expected: 123, actual: target.Int);
            Assert.Equal(expected: 123m, actual: target.Decimal);
    
            //This will throw an exception
            //Mapper.Instance.Map<Target>(new Source { String = "123.2" });
        }
    
    0 讨论(0)
  • 2020-12-30 02:17

    You could create properties in your source class that cast fields to the types as they exist in the destination. Then use AutoMapper in a plain vanilla manner.

    public class source
    {
      public int _myfield;
    
      public string MyField
      {
        get
        {
           return _myfield.ToString();
        }
      }
    }
    
    public class destination
    {
      public string MyField { get; set; }
    }
    
    0 讨论(0)
提交回复
热议问题