#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 сделать это напрямую. У меня есть несколько разных отображений, для которых мне нужно это сделать, и мне бы не хотелось добавлять все эти дополнительные классы в проект.