Skip to content

Mapping Properties of different types, No default constructor for type 'CultureInfo', please use 'ConstructUsing' or 'MapWith' #573

@codelovercc

Description

@codelovercc

Hi,

I use Mapster with version 7.3.0 and .Net 7.0.1

I have two classes.

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!;
}

And with mapster config

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);

Now execute this code

//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(); throws a Mapster.CompileException: Error while compiling.

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'

I tried use MapWith and it worked.

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);

This configuration didn't work.

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

dto => CultureInfo.GetCultureInfo(dto.CultureName) should work to create an instance of CultureInfo with out a constructor.

Is there something I missed or is this a bug?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions