Преобразовать строковое свойство ExpandoObject в DateTime с помощью Automapper

#c# #automapper #expandoobject

#c# #automapper #expandoobject

Вопрос:

Я хочу использовать Automapper для преобразования ExpandoObject в стандартный объект. Проблема в том, что некоторые свойства необходимо преобразовать из строк в DateTime, где строки DateTime являются нестандартными.

Вот несколько примеров кода:

 class Program
{
    public static void Main(string[] args)
    {
        dynamic src = new ExpandoObject();
        src.Name = "Joe";
        src.MyDateTime = "0619201359";  //mmddyyhhmm format
        src.MyDate = "121515";          //mmddyy format

        src.testDate = DateTime.Today;

        var configuration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<string, DateTime>().ConvertUsing(new MyDateTimeConverter()); 
        });
        configuration.AssertConfigurationIsValid();

        var mapper = configuration.CreateMapper();

        Destination des = mapper.Map<Destination>(src);

        Console.WriteLine($"Name : {des.Name}");
        Console.WriteLine($"MyDate: {des.MyDate}");
        Console.WriteLine($"MyDateType {des.MyDateTime}");
    }
}

public class MyDateTimeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(string date, DateTime destination, ResolutionContext context)
    {
        var dateFormat = date.Length switch
        {
            6 => "MMddyy",
            10 => "MMddyyHHmm",
            _ => throw new NotImplementedException($"Date format of {date} not implemented.")
        };

        return DateTime.ParseExact(date, dateFormat, new CultureInfo("en-US"));
    }
}

public class Destination
{
    public string Name { get; set; }
    public DateTime MyDate { get; set; }
    public DateTime MyDateTime { get; set; }
}

  

Когда я запускаю этот код, я получаю эту ошибку:

 Unhandled exception. AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
Object -> Destination
System.Object -> Destination
 ---> System.InvalidCastException: Unable to cast object of type 'System.Func`4[System.Object,System.Object,AutoMapper.ResolutionContext,System.DateTime]' to type 'System.Func`4[System.Object,System.Object,AutoMapper.ResolutionContext,System.Object]'.
   at AutoMapper.MapperConfiguration.GetExecutionPlan[TSource,TDestination](MapRequest mapRequest)
   at AutoMapper.Mapper.MapCore[TSource,TDestination](TSource source, TDestination destination, ResolutionContext context, Type sourceType, Type destinationType, IMemberMap memberMap)
   at AutoMapper.Mapper.AutoMapper.IInternalRuntimeMapper.Map[TSource,TDestination](TSource source, TDestination destination, ResolutionContext context, Type sourceType, Type destinationType, IMemberMap memberMap)
   at AutoMapper.ResolutionContext.Map(Object source, Object destination, Type sourceType, Type destinationType, IMemberMap memberMap)
   at AutoMapper.Internal.ReflectionHelper.MapMember(ResolutionContext context, MemberInfo member, Object value, Object destination)
   at AutoMapper.Mappers.FromStringDictionaryMapper.Map[TDestination](IDictionary`2 source, TDestination destination, ResolutionContext context, ProfileMap profileMap)
   at lambda_method(Closure , Object , Destination , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , Object , Destination , ResolutionContext )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at ConsoleApp1.Program.Main(String[] args) in C:UsersBrucesourcereposSandBoxConsoleApp1Program.cs:line 35
  

Я предполагаю, что проблема в настройке MapperConfiguration. Я пробовал несколько различных способов настройки ITypeConverter — безрезультатно. Из моих исследований я понял, что преобразования ExpandoObjects встроены в Automapper; поэтому вы не можете создать cfg.Создайте карту между ExpandoObject и объектом назначения.

Я не знаю, что делать. У кого-нибудь есть мысли о том, как это сделать? Спасибо за любую помощь.

Комментарии:

1. Попробуйте сборку MyGet .

2. @LucianBargaoanu Это, казалось, исправило это. Спасибо

Ответ №1:

Объявить класс Foo

 public class Foo
{
    public string Name { get; set; }
    public string MyDate { get; set; }
    public string MyDateTime { get; set; }
}
  

Добавить дополнительную конфигурацию сопоставления —

 cfg.CreateMap<Foo, Destination>();
  

Теперь сначала сопоставьте из ExpandoObject в Foo , затем из Foo в Destination

 Foo foo = mapper.Map<Foo>(src);
Destination destination = mapper.Map<Destination>(foo);
  

Комментарии:

1. Спасибо @atiyar. Это, безусловно, сработало бы, но я надеюсь, что есть способ заставить Automapper сделать это напрямую. У меня есть несколько разных отображений, для которых мне нужно это сделать, и мне бы не хотелось добавлять все эти дополнительные классы в проект.