MapsterMapper / Mapster

A fast, fun and stimulating object to object Mapper
MIT License
4.23k stars 325 forks source link

Base class private setters not mapped to #671

Closed luczito closed 4 months ago

luczito commented 5 months ago

I have an issue where a base class property with private setters are mapped to "null" when mapping a derived class.

I have the following setup:

class BaseDto {
   public int foo {get; private set;}
   public int bar {get; set;}

   public BaseDto()
   {
   }

   public BaseDto(int foo, int bar)
   {
      foo = foo;
      bar = bar;
   }
}
class DerivedDto : BaseDto {
   public int baz {get; set;}

   public DerivedDto(int baz, int foo, int bar) : base(foo, bar)
   {
      baz = baz;
   }
   public DerivedDto()
   {
   }
}  

And the same domain types but with public setters. When mapping:

domain.Adapt<DerivedDto>();

baz and bar gets assigned but foo is always null, i've tried defining a mapping config as:

config.newConfig<domain, baseDerived>()
   .MapToConstructor(true);

But this does not change the result. Is this an issue or am I missing something from the docs regarding mapping to private setters?

stagep commented 5 months ago

I have created an example that works. You have 2 issues. In the constructor when you have foo = foo; you are not doing any assignment. You would have to do this.foo = foo. Typically properties would be capitalized and then Foo = foo would be doing an assignment. The second issue is that you have a parameterless constructor so this constructor is used in the mapping.

using Mapster;

var domain = new Domain { Foo = 1, Bar = 2, Baz = 3 };
var derivedDto = domain.Adapt<DerivedDto>();

Console.WriteLine("Foo:{0} Bar:{1} Baz:{2}", derivedDto.Foo, derivedDto.Bar, derivedDto.Baz);

public class MapsterConfiguration : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<Domain, DerivedDto>()
            .MapToConstructor(true);
    }
}

class BaseDto
{
    public int Foo { get; private set; }
    public int Bar { get; set; }

    public BaseDto(int foo, int bar)
    {
        Foo = foo;
        Bar = bar;
    }
}
class DerivedDto : BaseDto
{
    public int Baz { get; set; }

    public DerivedDto(int baz, int foo, int bar) : base(foo, bar)
    {
        Baz = baz;
    }
}

class Domain
{
    public int Foo { get; init; }
    public int Bar { get; init; }
    public int Baz { get; init; }
}