Skip to content

Generic user mapping function overwrites specified function on other parameter #2277

@kammerjaeger

Description

@kammerjaeger

Please do the checklist before filing an issue:

  • I have read the documentation, including the FAQ
  • I can reproduce the bug using the latest prerelease version
  • I have searched existing discussion and issue to avoid duplicates

Describe the bug
When using generic custom methods and non generic custom methods for different parameter in the same mapping, the generic is used even if a non generic was specified. My actual code uses mapping functions with ref parameters and also does not work.

My simplified tests are with explicit specifying the function as I could better pin the problem down. In the last version (prev 8) using [UseStaticMapper(typeof(....))] instead of MapProperty, works so maybe related to #2275?

Please let me know what you think. Thanks!

Declaration code

public class GenericTestClassIn {
    public string? NullableStr { get; set; }
    public string Str { get; set; }
    public int AdditionalParameter { get; set; }
}
public class GenericTestClassOut {
    public string? NullableStr { get; set; }
    public string Str { get; set; }
    public int AdditionalParameter { get; set; }
}

public static class OtherMapper {
    public static string TrimToNull(string? input) => string.IsNullOrWhiteSpace(input) ? null : input;
    public static string Trim(string input) => input.Trim();
    public static T Identity<T>(T input) => input;
}

[Mapper]
public static partial class OtherTestMapper {
    [MapProperty(nameof(GenericTestClassIn.NullableStr), nameof(GenericTestClassOut.NullableStr), Use = nameof(@OtherMapper.TrimToNull))]
    [MapProperty(nameof(GenericTestClassIn.Str), nameof(GenericTestClassOut.Str), Use = nameof(@OtherMapper.Trim))]
    [MapProperty(nameof(GenericTestClassIn.AdditionalParameter), nameof(GenericTestClassOut.AdditionalParameter), Use = nameof(@OtherMapper.Identity))]
    public static partial GenericTestClassOut Map(GenericTestClassIn input);

    [MapProperty(nameof(GenericTestClassIn.NullableStr), nameof(GenericTestClassOut.NullableStr), Use = nameof(@OtherMapper.TrimToNull))]
    [MapProperty(nameof(GenericTestClassIn.Str), nameof(GenericTestClassOut.Str), Use = nameof(@OtherMapper.Trim))]
    [MapProperty(nameof(GenericTestClassIn.AdditionalParameter), nameof(GenericTestClassOut.AdditionalParameter), Use = nameof(@OtherMapper.Identity))]
    public static partial void Update(GenericTestClassIn input, [MappingTarget] GenericTestClassOut target);
}

Actual relevant generated code

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "5.0.0.0")]
        public static partial global::Tests.Model.Mapper.GenericTestClassOut Map(global::Tests.Model.Mapper.GenericTestClassIn input)
        {
            var target = new global::Tests.Model.Mapper.GenericTestClassOut();
            target.NullableStr = global::Tests.Model.Mapper.OtherMapper.Identity<string>(input.NullableStr);
            target.Str = global::Tests.Model.Mapper.OtherMapper.Identity<string>(input.Str);
            target.AdditionalParameter = global::Tests.Model.Mapper.OtherMapper.Identity<int>(input.AdditionalParameter);
            return target;
        }

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "5.0.0.0")]
        public static partial void Update(global::Tests.Model.Mapper.GenericTestClassIn input, global::Tests.Model.Mapper.GenericTestClassOut target)
        {
            target.NullableStr = global::Tests.Model.Mapper.OtherMapper.Identity<string>(input.NullableStr);
            target.Str = global::Tests.Model.Mapper.OtherMapper.Identity<string>(input.Str);
            target.AdditionalParameter = global::Tests.Model.Mapper.OtherMapper.Identity<int>(input.AdditionalParameter);
        }

Expected relevant generated code

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "5.0.0.0")]
        public static partial global::Tests.Model.Mapper.GenericTestClassOut Map(global::Tests.Model.Mapper.GenericTestClassIn input)
        {
            var target = new global::Tests.Model.Mapper.GenericTestClassOut();
            target.NullableStr = global::Tests.Model.Mapper.OtherMapper.TrimToNull(input.NullableStr);
            target.Str = global::Tests.Model.Mapper.OtherMapper.Trim(input.Str);
            target.AdditionalParameter = global::Tests.Model.Mapper.OtherMapper.Identity<int>(input.AdditionalParameter);
            return target;
        }

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "5.0.0.0")]
        public static partial void Update(global::Tests.Model.Mapper.GenericTestClassIn input, global::Tests.Model.Mapper.GenericTestClassOut target)
        {
            target.NullableStr = global::Tests.Model.Mapper.OtherMapper.TrimToNull(input.NullableStr);
            target.Str = global::Tests.Model.Mapper.OtherMapper.Trim(input.Str);
            target.AdditionalParameter = global::Tests.Model.Mapper.OtherMapper.Identity<int>(input.AdditionalParameter);
        }

Environment (please complete the following information):

  • Mapperly Version: 5.0.0-next.8
  • Nullable reference types: enabled
  • .NET Version: NET 10.0.203
  • Target Framework: .net10.0
  • Compiler Version: 5.3.0-2.26219.105 (c23858a6d860abe3ca94f9ac630c3e61b2625664)
  • C# Language Version: 14.0
  • IDE: Visual Studio v18.5.0
  • OS: Win 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions