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<>))]
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<>))]
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<>))]
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<>))]
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<>))]
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<>))]
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