Mapster: сопоставление свойств разных типов. Для типа «CultureInfo» нет конструктора по умолчанию, используйте «ConstructUsing» или «MapWith».

Я использую Mapster версии 7.3.0 и .Net 7.0.1.

У меня два класса.

      public class Entity
{
    public Guid Id { get; set; }

    public string Content { get; set; } = default!;

    public string Note { get; set; } = default!;

    public CultureInfo CultureInfo { get; set; } = default!;
}

public class Dto
{
    [Required, StringLength(64)]
    public string Id { get; set; } = default!;

    [Required, StringLength(4096)]
    public string Content { get; set; } = default!;

    [Required, StringLength(1024)]
    public string Note { get; set; } = default!;

    [Required]
    public string CultureName { get; set; } = default!;
}

И с конфигом Mapster

      TypeAdapterConfig<Dto, Entity>.NewConfig()
            .Map(entity => entity.CultureInfo, dto => CultureInfo.GetCultureInfo(dto.CultureName));
TypeAdapterConfig<Entity, Dto>.NewConfig()
            .Map(dto => dto.CultureName, entity => entity.CultureInfo.Name);

Теперь выполните этот код

      //Mapster configuration is applied.

var dto = new Dto
        {
            Id = Guid.NewGuid().ToString(),
            Content = "this is a test content",
            Note = "for test",
            CultureName = "zh-CN"
        };
        var mLocal = dto.Adapt<Entity>();

var mLocal = dto.Adapt<Entity>();выдает Mapster.CompileException: ошибка при компиляции.

      Mapster.CompileException: Error while compiling

Mapster.CompileException
Error while compiling
source=MindOcean.Models.Common.MessageTemplateLocalizerDto
destination=MindOcean.Data.Entities.MessageTemplateLocalizer
type=Map
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateMapExpression(TypeTuple tuple, MapType mapType)
   at Mapster.TypeAdapterConfig.CreateDynamicMapExpression(TypeTuple tuple)
   at Mapster.TypeAdapterConfig.<GetDynamicMapFunction>b__66_0[TDestination](TypeTuple tuple)
   at Mapster.TypeAdapterConfig.<>c__DisplayClass55_0`1.<AddToHash>b__0(TypeTuple types)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Mapster.TypeAdapterConfig.AddToHash[T](ConcurrentDictionary`2 hash, TypeTuple key, Func`2 func)
   at Mapster.TypeAdapterConfig.GetDynamicMapFunction[TDestination](Type sourceType)
   at Mapster.TypeAdapter.Adapt[TDestination](Object source, TypeAdapterConfig config)
   at Mapster.TypeAdapter.Adapt[TDestination](Object source)
   at MindOcean.Test.UnitTest.MapsterTester.TestTwoWay() in /Test/MapsterTester.cs:line 71
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

Mapster.CompileException
Error while compiling
source=System.Globalization.CultureInfo
destination=System.Globalization.CultureInfo
type=Map
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context, MemberMapping mapping)
   at Mapster.Adapters.BaseAdapter.CreateAdaptExpressionCore(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
   at Mapster.Adapters.BaseAdapter.CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
   at Mapster.Adapters.ClassAdapter.CreateInlineExpression(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateInlineExpressionBody(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)

System.InvalidOperationException
No default constructor for type 'CultureInfo', please use 'ConstructUsing' or 'MapWith'
   at Mapster.Adapters.BaseAdapter.CreateInstantiationExpression(Expression source, Expression destination, CompileArgument arg)
   at Mapster.Adapters.ClassAdapter.CreateInstantiationExpression(Expression source, Expression destination, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateInstantiationExpression(Expression source, CompileArgument arg)
   at Mapster.Adapters.ClassAdapter.CreateInlineExpression(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateInlineExpressionBody(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)

No default constructor for type 'CultureInfo', please use 'ConstructUsing' or 'MapWith'

Я попробовал использовать MapWith, и это сработало.

      TypeAdapterConfig<Dto, Entity>.NewConfig()
     .MapWith(dto => new Entity
     {
         CultureInfo = CultureInfo.GetCultureInfo(dto.CultureName),
         Id = Guid.Parse(dto.Id),
         Content = dto.Content,
         Note = dto.Note,
     });
TypeAdapterConfig<Entity, Dto>.NewConfig()
            .Map(dto => dto.CultureName, entity => entity.CultureInfo.Name);

я предпочитаюTypeAdapterConfig<Dto, Entity>.NewConfig()Сюда. Если в доме много объектовEntityкласс, и мне нужно только настроитьCultureInfoсвойство, настройка остальных свойств не требуется, поэтому мне не нужно писать так много ненужного кода. как будто я конвертирую вручную и с большим количеством ненужного кода.

Я хочу знать, есть ли другой способ, а не MapWithрешить эту проблему конфигурации картографирования Mapster?

1 ответ

Не знаю, почему это не работает, но по крайней мере одним обходным решением может быть игнорирование члена и использование действия после сопоставления:

      TypeAdapterConfig<Dto, Entity>.NewConfig()
    .Ignore(e => e.CultureInfo)
    .AfterMapping((d, e) => e.CultureInfo = CultureInfo.GetCultureInfo(d.CultureName));
Другие вопросы по тегам