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

Generated mappers and required attributes #554

Open
EniacMlezi opened this issue Feb 27, 2023 · 12 comments · May be fixed by #778
Open

Generated mappers and required attributes #554

EniacMlezi opened this issue Feb 27, 2023 · 12 comments · May be fixed by #778

Comments

@EniacMlezi
Copy link
Contributor

EniacMlezi commented Feb 27, 2023

When using the c#11.0 required feature, the generated mappers fail. Editinh Sample.CodeGen for example:

public class Person
{
    public required int ID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
}

And looking at the generated StudentMapper:
image

@EniacMlezi EniacMlezi changed the title Mappers and required attributes Generated mappers and required attributes Feb 27, 2023
@stormaref
Copy link
Contributor

stormaref commented Mar 4, 2023

@andrerav should we remove this part entirely and just generate the part with initialization values?
@EniacMlezi can you mention the complete source code, please

@andrerav
Copy link
Contributor

andrerav commented Mar 5, 2023

@stormaref That is tempting, but it will change a lot of code for a lot of people. I think a similar solution to the one in #545 is preferable.

@stormaref
Copy link
Contributor

@andrerav that fix won't work with this problem because in that case, the problem was setting the init-only property, and this line was ok:

_UserDto result = p4 ?? new _UserDto();

but in this case, the problem occurs on this line:

Person result = p4 ?? new Person();

and that solution won't fix this problem

@EniacMlezi
Copy link
Contributor Author

@EniacMlezi can you mention the complete source code, please

The complete source code is the codegen sample in this repository (Sample.CodeGen), but with Person.Id made required and the C# langver set to support required.

@EniacMlezi
Copy link
Contributor Author

Check this: for code sample: EniacMlezi@3840103

@leetal
Copy link

leetal commented Feb 25, 2025

Has anyone found a solution to this?

@DocSvartz
Copy link

@andrerav
This part of the code is generated by NullPropagation. Improvement should be done there.

@DocSvartz
Copy link

@andrerav @leetal This is what you need, right?

.Lambda #Lambda1<System.Func`3[Mapster.Tests.Person554,Mapster.Tests.Person554,Mapster.Tests.Person554]>(
    Mapster.Tests.Person554 $var1,
    Mapster.Tests.Person554 $var2) {
    .Block(Mapster.Tests.Person554 $result) {
        .If ($var1 == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        $result = ($var2 ?? .New Mapster.Tests.Person554(){
            ID = $var1.ID   // generate this only for the required property
        });
        .Block() {
            $result.ID = $var1.ID;
            $result.LastName = $var1.LastName;
            $result.FirstMidName = $var1.FirstMidName
        };
        .Return #Label1 { $result };
        .Label
            null
        .LabelTarget #Label1:
    }
}

@leetal
Copy link

leetal commented Feb 25, 2025

Essentially, yes :) But I fear that it might not work if using for example different classes and say that the required property would be non-existent (in your var1 above) by having custom DTOs with mapping configs as an example, then that would not work right? What would be a “sensible default” in those cases without having a way to actually populate the required field somehow? Or am I completely wrong? 🤔

@DocSvartz
Copy link

DocSvartz commented Feb 25, 2025

If you use configuration. Then it will work too.

var source = new Person553 {  FirstMidName = "John", LastName = "Dow" }; // not Id
var destination = new Person554 { ID = 245, FirstMidName = "Mary", LastName = "Dow" };

TypeAdapterConfig<Person553, Person554>.NewConfig()
    .Map(dest => dest.ID, source => 0);
.Lambda #Lambda1<System.Func`3[Mapster.Tests.Person553,Mapster.Tests.Person554,Mapster.Tests.Person554]>(
    Mapster.Tests.Person553 $var1,
    Mapster.Tests.Person554 $var2) {
    .Block(Mapster.Tests.Person554 $result) {
        .If ($var1 == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        $result = ($var2 ?? .New Mapster.Tests.Person554(){
            ID = 0
        });
        .Block() {
            $result.ID = 0;
            $result.LastName = $var1.LastName;
            $result.FirstMidName = $var1.FirstMidName
        };
        .Return #Label1 { $result };
        .Label
            null
        .LabelTarget #Label1:
    }
}

Without configuration, yes, it will not work.
But can try to add the ability to set a default value for the type :)

@DocSvartz
Copy link

DocSvartz commented Feb 25, 2025

With this configuration, the result will be correct. (not work on 7.4.0)

var source = new Person553 {  FirstMidName = "John", LastName = "Dow" };
var destination = new Person554 { ID = 245, FirstMidName = "Mary", LastName = "Dow" };

TypeAdapterConfig<Person553, Person554>.NewConfig()
    .Map(dest => dest.ID, source => 0)
    .Ignore(x=>x.ID);
.Lambda #Lambda1<System.Func`3[Mapster.Tests.Person553,Mapster.Tests.Person554,Mapster.Tests.Person554]>(
    Mapster.Tests.Person553 $var1,
    Mapster.Tests.Person554 $var2) {
    .Block(Mapster.Tests.Person554 $result) {
        .If ($var1 == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        $result = ($var2 ?? .New Mapster.Tests.Person554(){
            ID = 0
        });
        .Block() {
            // id  is not modified  
            $result.LastName = $var1.LastName;              // update from source (var1)
            $result.FirstMidName = $var1.FirstMidName // update from source (var1)
        };
        .Return #Label1 { $result };
        .Label
            null
        .LabelTarget #Label1:
    }
}

@DocSvartz DocSvartz linked a pull request Feb 26, 2025 that will close this issue
@DocSvartz DocSvartz linked a pull request Feb 26, 2025 that will close this issue
@DocSvartz
Copy link

DocSvartz commented Feb 26, 2025

@andrerav I opened a PR that I hope adds this improvement. ))
But additional test samples or testing within the Prerelease are needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants