riok / mapperly

A .NET source generator for generating object mappings. No runtime reflection.
https://mapperly.riok.app
Apache License 2.0
2.68k stars 144 forks source link

Pass additional parameters to property mapper methods #1472

Open Demivan opened 2 months ago

Demivan commented 2 months ago

Is your feature request related to a problem? Please describe. I'm trying to migrate this AutoMapper code to Mapperly:

.ForMember(
     blog => blog.IsLiked,
     cfg => cfg.MapFrom(record => record.BlogLikeRecord.Any(bl => bl.UserId == currentUserId)));

This currently does not work.

[Mapper(AutoUserMappings = false)]
public static partial class BlogsMapper
{
    [MapPropertyFromSource(nameof(BlogEntry.IsLiked), Use = nameof(GetIsLiked))]
    public static partial BlogEntry MapToBlogEntry(BlogEntryRecord record, int currentUserId);

    public static partial IQueryable<BlogEntry> ProjectToBlogEntry(this IQueryable<BlogEntryRecord> query, int currentUserId);

    private static bool GetIsLiked(BlogEntryRecord record, int currentUserId) => record.BlogLikeRecord.Any(bl => bl.UserId == currentUserId);
}

Describe the solution you'd like When parametes name and type match, pass additional parameters from Map/Project method to a property mapping methods.

// <auto-generated />
#nullable enable
namespace Blogs
{
    public static partial class BlogsMapper
    {
        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.0.0.0")]
        public static partial global::Blogs.BlogEntry MapToBlogEntry(global::Blogs.BlogEntryRecord record, int currentUserId)
        {
            var target = new global::Blogs.BlogEntry();
            target.IsLiked = GetIsLiked(record, currentUserId);
            return target;
        }

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.0.0.0")]
        public static partial global::System.Linq.IQueryable<global::Blogs.BlogEntry> ProjectToBlogEntry(this global::System.Linq.IQueryable<global::Blogs.BlogEntryRecord> query, int currentUserId)
        {
#nullable disable
            return System.Linq.Queryable.Select(
                query,
                x => new global::Blogs.BlogEntry()
                {
                    IsLiked = x.BlogLikeRecord.Any(bl => bl.UserId == currentUserId)
                }
            );
#nullable enable
        }
    }
}

Describe alternatives you've considered Move this logic outside of a mapper could be a solution. But, I think, Mapperly should be able to support this.

Demivan commented 2 months ago

And there seems to be a bug that IQueryable projections do not work with additional parameters.