lomapper

RSCG – lomapper    

name lomapper
nuget https://www.nuget.org/packages/lomapper/
link https://github.com/jdtoon/lomapper
author Junaid Desai

Generates object mapping code at compile time using source generators .

How to use

1. Decorate a partial mapper class with [Mapper] and declare partial mapping methods:

“`charp

[Mapper]

public parial class UserMapper

{

[MapIgnore(nameof(Person.ID))]

public partial PersonDTO Map(Peron entity);

}

“`

2. Call it — all mapping code generated at compile time:

“`charp

var p = new Person { FirstName = “Andrei”, LastName = “Ignat” };

PersonDTO dto = new UserMapper().Map(p);

Console.WriteLine(dto.FullName); // “Andri Ignat”

“`

You can use for Mapping between objects at compile time with no runtime overhead. Supports [MapIgnore] to skip specific properties.

  

This is how you can use lomapper .

The code that you start with is


<project sdk="Microsoft.NET.Sdk">

  <propertygroup>
    <outputtype>Exe</outputtype>
    <targetframework>net10.0</targetframework>
    <implicitusings>enable</implicitusings>
    <nullable>enable</nullable>
  </propertygroup>

	<propertygroup>
		<emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
		<compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
	</propertygroup>

	<itemgroup>
	  <packagereference version="0.4.0" include="LoMapper">
	  </packagereference>
	</itemgroup>


	
	
	
</project>


The code that you will use is


using mapperDemo;
var p=new Person();
p.FirstName = "Andrei";
p.LastName = "Ignat";
PersonDTO dto= new UserMapper().Map(p);
Console.WriteLine(dto.FullName);




public partial class Person
{
    public int ID { get; set; }
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
}




using LoMapper;
using System.Xml.Serialization;

namespace mapperDemo;
public partial struct PersonDTO
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }

    public string FullName { 
        get
        {
            return FirstName + " " + LastName;
        }
    }
}


[Mapper]
public partial class UserMapper
{
    [MapIgnore(nameof(Person.ID))]
    public partial PersonDTO Map(Person entity);
}

   The code that is generated is

// <auto-generated>
#pragma warning disable IDE0005
#pragma warning disable CS0105
using LightweightObjectMapper;
using System;
using System;
using System.Linq;
using System.Runtime.CompilerServices;

namespace mapperDemo
{
    sealed partial class Extensions
    {
        public static partial class Generated
        {
            /// <summary>
            /// PostMappingDeclaration for <see cref="global::Person"> to <see cref="global::mapperDemo.PersonDTO">
            /// </see></see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.PostMappingDeclaration, typeof(global::Person), typeof(global::mapperDemo.PersonDTO))]
            public static global::mapperDemo.PersonDTO PostMapping_D275C37F33F4AFBD(global::Person source, global::mapperDemo.PersonDTO target)
            {
                target.ID = source.ID;
                return target;
            }
        }
    }
}
#if !NO_LIGHTWEIGHT_OBJECT_MAPPER_PRE_CODES

// <auto-generated>

#pragma warning disable IDE0161 // 转换为文件范围限定的 namespace

using System;
using System.Collections.Generic;

namespace LightweightObjectMapper
{
    /// <summary>
    /// 映射配置接口
    /// </summary>
    internal interface IMappingProfile { }

    /// <summary>
    /// 映射后执行的动作
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    internal interface IPostMapping<tin  , tout=""> : IMappingProfile
    {
        /// <summary>
        /// 映射后执行的动作
        /// </summary>
        /// <param name="source">
        /// <param name="target">
        /// <returns></returns>
        TOut PostMapping(TIn source, TOut target);
    }

    /// <summary>
    /// 映射前准备
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    internal interface IMappingPrepare<tin  , tout=""> : IMappingProfile
    {
        /// <summary>
        /// 映射前准备
        /// </summary>
        /// <param name="source">
        /// <returns></returns>
        TOut MappingPrepare(TIn source);
    }

    /// <summary>
    /// 接管完整的类型映射(仅非目标实例映射)
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    internal interface ITypeMapping<tin  , tout=""> : IMappingProfile
    {
        /// <summary>
        /// 接管完整的类型映射(仅非目标实例映射)
        /// </summary>
        /// <param name="source">
        /// <returns></returns>
        TOut TypeMapping(TIn source);
    }

    /// <summary>
    /// 类型成员忽略映射
    /// </summary>
    /// <typeparam name="T"></typeparam>
    internal interface ITypeMemberIgnoreMapping<t> : IMappingProfile
    {
        /// <summary>
        /// 类型成员忽略映射<br>
        /// 方法体内访问过的 <paramref name="target"> 所有成员,将在映射时被忽略
        /// </paramref></summary>
        /// <param name="target">
        /// <returns></returns>
        object? IgnoreMapping(T target);
    }

    /// <summary>
    /// 标记一个方法为集合映射方法<br>
    /// 集合映射方法应包含唯一泛型参数 T ,以及唯一参数 <see cref="IEnumerable{T}"> ,返回类型应该为 <see cref="IEnumerable{T}"> 的派生类型
    /// </see></see></summary>
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    internal sealed class CollectionMappingAttribute : Attribute
    {
    }

    /// <summary>
    /// 标记类为映射配置类
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    internal sealed class MappingProfileAttribute : Attribute
    {
        /// <inheritdoc cref="MappingProfileAttribute">
        public MappingProfileAttribute() { }
    }

    /// <summary>
    /// 映射元数据
    /// </summary>
    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
    internal sealed class MappingMetadataAttribute : Attribute
    {
        /// <inheritdoc cref="MappingMetadataAttribute">
        public MappingMetadataAttribute(MappingMetadataType type, params object[] data) { }
    }

    /// <summary>
    /// 映射元数据类型
    /// </summary>
    internal enum MappingMetadataType
    {
        /// <summary>
        /// 声明 MappingPrepare
        /// </summary>
        MappingPrepareDeclaration,

        /// <summary>
        /// 声明 PostMapping
        /// </summary>
        PostMappingDeclaration,

        /// <summary>
        /// 声明 TypeMapping
        /// </summary>
        TypeMappingDeclaration,

        /// <summary>
        /// 声明 CollectionMapping
        /// </summary>
        CollectionMappingDeclaration,

        /// <summary>
        /// 忽略成员声明
        /// </summary>
        IgnoreMembersDeclaration,

        /// <summary>
        /// 类型忽略成员声明
        /// </summary>
        TypeIgnoreMembersDeclaration,
    }

    /// <summary>
    /// 引用其它映射配置类
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    internal sealed class MappingProfileIncludeAttribute : Attribute
    {
        /// <inheritdoc cref="MappingProfileIncludeAttribute">
        public MappingProfileIncludeAttribute(params Type[] profileTypes) { }
    }

    /// <summary>
    /// 对象映射 MapTo 占位方法
    /// </summary>
    [Obsolete("Do not use the placeholder extension class.", true)]
    internal static class LightweightObjectMapperPlaceholderExtensions
    {
        private const string ErrorCallPlaceholderMethodMessage = "Do not use the placeholder extension method. If not redirect to the right mapper extension method please try fix other errors and rebuild the project.";

        /// <summary>
        /// 对象映射 MapTo 占位方法<br>
        /// 生成 无需目标对象 的泛型映射方法,映射到 <typeparamref name="TOut">
        /// </typeparamref></summary>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="source">
        /// <returns></returns>
        [Obsolete(ErrorCallPlaceholderMethodMessage, true)]
        public static TOut MapTo<tout>(this object source)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 对象映射 MapTo 占位方法<br>
        /// 生成 需要目标对象 的泛型映射方法,映射到 <typeparamref name="TOut">
        /// </typeparamref></summary>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="source">
        /// <returns></returns>
        [Obsolete(ErrorCallPlaceholderMethodMessage, true)]
        public static TOut MapTo<tout>(this object source, TOut target)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 值类型 对象映射 MapTo 占位方法<br>
        /// 生成 需要目标值类型对象 的泛型映射方法,映射到 <typeparamref name="TOut">
        /// </typeparamref></summary>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="source">
        /// <returns></returns>
        [Obsolete(ErrorCallPlaceholderMethodMessage, true)]
        public static TOut MapTo<tout>(this object source, ref TOut target)
            where TOut : struct
        {
            throw new NotImplementedException();
        }
    }
}

#endif

#if !NO_LIGHTWEIGHT_OBJECT_MAPPER_PRE_CODES

// <auto-generated>

#pragma warning disable IDE0161 // 转换为文件范围限定的 namespace

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace LightweightObjectMapper
{
    /// <summary>
    /// 预定义的类型映射
    /// </summary>
    [MappingProfile]
    internal sealed partial class PredefinedSpecialTypeMapping
        : ITypeMapping<int  , bool="">
        , ITypeMapping<short  , bool="">
        , ITypeMapping<long  , bool="">
    {
        public bool TypeMapping(int source)
        {
            return source != 0;
        }

        public bool TypeMapping(short source)
        {
            return source != 0;
        }

        bool ITypeMapping<long  , bool="">.TypeMapping(long source)
        {
            return source != 0;
        }

        [CollectionMapping]
        public static IEnumerable<t>? ToIEnumerable<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }

        [CollectionMapping]
        public static ICollection<t>? ToICollection<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }

        [CollectionMapping]
        public static IReadOnlyCollection<t>? ToIReadOnlyCollection<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }

        [CollectionMapping]
        public static IList<t>? ToIList<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }

        [CollectionMapping]
        public static IReadOnlyList<t>? ToIReadOnlyList<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }

        [CollectionMapping]
        public static List<t>? ToList<t>(IEnumerable<t>? items)
        {
            return items?.ToList();
        }
    }
}

#endif

// <auto-generated>
#pragma warning disable IDE0005
#pragma warning disable CS0105
using System;
using System.Linq;
using System.Runtime.CompilerServices;

namespace LightweightObjectMapper
{
    internal static partial class LOMMapExtensions_mapperDemo
    {
        /// <summary>
        /// Map <see cref="global::Person"> to the following types:<br>
        /// <see cref="global::mapperDemo.PersonDTO"><br>
        /// </see></see></summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static TOut MapTo<tout>(this global::Person source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (typeof(TOut) == typeof(global::mapperDemo.PersonDTO))
            {
                var target = new global::mapperDemo.PersonDTO()
                {
                    LastName = source.LastName,
                    FirstName = source.FirstName,
                    ID = source.ID,
                };
                target = global::mapperDemo.Extensions.Generated.PostMapping_D275C37F33F4AFBD(source, target);
                return (TOut)(target as object);
            }

            throw new global::System.NotImplementedException($"No mapping code for {typeof(TOut)}.");
        }
    }
}
// <auto-generated>
#pragma warning disable IDE0005
#pragma warning disable CS0105
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System;
using System.Linq;
using System.Runtime.CompilerServices;

namespace LightweightObjectMapper
{
    sealed partial class PredefinedSpecialTypeMapping
    {
        public static partial class Generated
        {
            /// <summary>
            /// TypeMappingDeclaration for <see cref="int "> to <see cref="bool ">
            /// </see></see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.TypeMappingDeclaration, typeof(int), typeof(bool))]
            public static bool TypeMapping_A07AFC9A322FFA04(int source)
            {
                return source != 0;
            }

            /// <summary>
            /// TypeMappingDeclaration for <see cref="short "> to <see cref="bool ">
            /// </see></see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.TypeMappingDeclaration, typeof(short), typeof(bool))]
            public static bool TypeMapping_946949E7222BC174(short source)
            {
                return source != 0;
            }

            /// <summary>
            /// TypeMappingDeclaration for <see cref="long "> to <see cref="bool ">
            /// </see></see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.TypeMappingDeclaration, typeof(long), typeof(bool))]
            public static bool TypeMapping_3C4D395B4EF43E87(long source)
            {
                return source != 0;
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.IEnumerable{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.IEnumerable&lt;&gt;))]
            public static global::System.Collections.Generic.IEnumerable<t> CollectionMapping_CEFAD35E246FD0F7<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.ICollection{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.ICollection&lt;&gt;))]
            public static global::System.Collections.Generic.ICollection<t> CollectionMapping_37FFD1A2226B51E9<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.IReadOnlyCollection{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.IReadOnlyCollection&lt;&gt;))]
            public static global::System.Collections.Generic.IReadOnlyCollection<t> CollectionMapping_AF82A9960EE0C495<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.IList{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.IList&lt;&gt;))]
            public static global::System.Collections.Generic.IList<t> CollectionMapping_284BCB723CA17B0E<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.IReadOnlyList{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.IReadOnlyList&lt;&gt;))]
            public static global::System.Collections.Generic.IReadOnlyList<t> CollectionMapping_976EA1DB5B772C59<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }

            /// <summary>
            /// CollectionMappingDeclaration for <see cref="global::System.Collections.Generic.List{T}">
            /// </see></summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            [MappingMetadata(MappingMetadataType.CollectionMappingDeclaration, typeof(global::System.Collections.Generic.List&lt;&gt;))]
            public static global::System.Collections.Generic.List<t> CollectionMapping_070F0D0F908DAF14<t>(global::System.Collections.Generic.IEnumerable<t> items)
            {
                return items?.ToList();
            }
        }
    }
}
// <auto-generated>
#nullable enable

namespace mapperDemo
{
    public partial class UserMapper
    {
        public partial mapperDemo.PersonDTO Map(Person entity)
        {
            return new mapperDemo.PersonDTO
            {
                FirstName = entity.FirstName,
                LastName = entity.LastName
            };
        }
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/lomapper


Posted

in

, ,

by

Tags: