Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot map properties that have differt names and init access modifier #656

Open
nicoarm93 opened this issue Nov 7, 2023 · 3 comments
Open

Comments

@nicoarm93
Copy link

nicoarm93 commented Nov 7, 2023

Hi,
I have a problem with version 7.4. If I want to map two properties with different names and the destination has a different name and the init modifier, Mapster throws a NullReferenceException. This happens when in the configuration of Mapster I set PreserveReference to true.

Here's the code

{
    public Mapper Mapper { get; }

    public MapsterTest()
    {
        var config = new TypeAdapterConfig();
        config.Default.Settings.PreserveReference = true;
        config.Scan(Assembly.GetAssembly(typeof(MapsterTest)));
        config.Compile();
        Mapper = new Mapper(config);
    }
}

internal class MyClass
{
    public int MyProperty { get; set; }
}

internal class DtoClass
{
    public int MyPropertyDto { get; init; }
}
internal class Register : IRegister
{
    void IRegister.Register(TypeAdapterConfig config)
    {
        config.NewConfig<MyClass, DtoClass>()
            .Map(x => x.MyPropertyDto, x=> x.MyProperty);
    }
}

And here's the mapping


var from = new MyClass { MyProperty = 1};

var to = mapster.Mapper.Map<DtoClass>(from);

(The problem does not manifest if the properties have the same name or another modifier (set; or private set;)
This code works fine with version 7.3

@DocSvartz
Copy link

DocSvartz commented Nov 12, 2023

linked #422

@nicoarm93 @andrerav location of this bug found )

PR with fix is open #658

@Mat3oo
Copy link

Mat3oo commented Dec 8, 2023

In my case similar regression between 7.4.0 and 7.3.0 (Mapster throws a NullReferenceException) is not related to PreserveReference. It's about init only properties, when mapping to target object.
Below code works fine with Mapster 7.3.0, but doesn't work with Mapster 7.4.0.

using Mapster;

TypeAdapterConfig<Core.RootSource.NestedSource, Core.RootDestination.NestedDestination>
    .NewConfig()
    .Map(dest => dest.NameDest, src => src.NameSrc);

var dest = new Core.RootDestination { MyProperty = null };

var mapped = Core.RootSource.Create().Adapt(dest);

Console.WriteLine(mapped);

namespace Core
{
    public class RootSource
    {
        public required NestedSource? MyProperty { get; set; }

        public static RootSource Create()
        {
            return new RootSource
            {
                MyProperty = new NestedSource
                {
                    NameSrc = "NotEmptyString"
                }
            };
        }

        public class NestedSource
        {
            public required string NameSrc { get; set; }
        }
    }

    public class RootDestination
    {
        public NestedDestination? MyProperty { get; set; }

        public override string ToString()
        {
            return $"{nameof(RootDestination)}.{nameof(MyProperty)}={MyProperty?.NameDest}";
        }

        public class NestedDestination
        {
            public string? NameDest { get; init; }
        }
    }
}

@DocSvartz
Copy link

Hello @Mat3oo, @andrerav
I checked my fix. The bug indicated by @Mat3oo persists.
The place of origin itself is most likely identified correctly.
But the created working code and the created non-working code, at first glance, do not make sense and both should not work))

Working Code :

.Lambda #Lambda1<System.Func`3[Core.RootSource+NestedSource,Core.RootDestination+NestedDestination,Core.RootDestination+NestedDestination]>(
    Core.RootSource+NestedSource $var1,
    Core.RootDestination+NestedDestination $var2) {
    .Block(Core.RootDestination+NestedDestination $result) {
        .If ($var1 == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        $result = ($var2 ?? .New Core.RootDestination+NestedDestination());
        .Block() {
            $result.NameDest = $var1.NameSrc
        };
        .Return #Label1 { $result };
        .Label
            null
        .LabelTarget #Label1:
    }
}

Non-working code (throws a NullReferenceException):

.Lambda #Lambda1<System.Func`3[Core.RootSource+NestedSource,Core.RootDestination+NestedDestination,Core.RootDestination+NestedDestination]>(
    Core.RootSource+NestedSource $var1,
    Core.RootDestination+NestedDestination $var2) {
    .Block(Core.RootDestination+NestedDestination $result) {
        .If ($var1 == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        $result = ($var2 ?? .New Core.RootDestination+NestedDestination());
        .Block() {
            .Call (.Call .Constant<System.RuntimeType>(Core.RootDestination+NestedDestination).GetProperty("NameSrc")).SetValue(
                $result,
                $var1.NameSrc)
        };
        .Return #Label1 { $result };
        .Label
            null
        .LabelTarget #Label1:
    }
}

SimTsai added a commit to SimTsai/Mapster that referenced this issue Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants