RSCG – Facet
| name | Facet |
| nuget | https://www.nuget.org/packages/Facet/ |
| link | https://github.com/Tim-Maes/Facet/ |
| author | Tim Maes |
Custom generation and mapper
This is how you can use Facet .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Facet" Version="2.7.0" />
</ItemGroup>
</Project>
The code that you will use is
using mapperDemo; var p=new Person(); p.FirstName = "Andrei"; p.LastName = "Ignat"; PersonDTO dto= new(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 Facet;
namespace mapperDemo;
[Facet(typeof(Person), Kind = FacetKind.Struct)]
public partial struct PersonDTO
{ public string FullName {
get
{
return FirstName + " " + LastName;
}
}
}
The code that is generated is
// <auto-generated>
// This code was generated by the Facet source generator.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
using System;
using System.Linq.Expressions;
namespace mapperDemo;
public partial struct PersonDTO
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PersonDTO"/> class from the specified <see cref="global::Person"/>.
/// </summary>
/// <param name="source">The source <see cref="global::Person"/> object to copy data from.</param>
public PersonDTO(global::Person source)
{
this.ID = source.ID;
this.FirstName = source.FirstName;
this.LastName = source.LastName;
}
/// <summary>
/// Initializes a new instance of the <see cref="PersonDTO"/> class with default values.
/// </summary>
/// <remarks>
/// This constructor is useful for unit testing, object initialization, and scenarios
/// where you need to create an empty instance and populate properties later.
/// </remarks>
public PersonDTO()
{
}
/// <summary>
/// Gets the projection expression for converting <see cref="global::Person"/> to <see cref="PersonDTO"/>.
/// Use this for LINQ and Entity Framework query projections.
/// </summary>
/// <value>An expression tree that can be used in LINQ queries for efficient database projections.</value>
/// <example>
/// <code>
/// var dtos = context.global::Persons
/// .Where(x => x.IsActive)
/// .Select(PersonDTO.Projection)
/// .ToList();
/// </code>
/// </example>
public static Expression<Func<global::Person, PersonDTO>> Projection =>
source => new PersonDTO(source);
}
// <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"/>
/// </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>
/// <param name="target"></param>
/// <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"></param>
/// <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"></param>
/// <returns></returns>
TOut TypeMapping(TIn source);
}
/// <summary>
/// 类型成员忽略映射
/// </summary>
/// <typeparam name="T"></typeparam>
internal interface ITypeMemberIgnoreMapping<T> : IMappingProfile
{
/// <summary>
/// 类型成员忽略映射<br/>
/// 方法体内访问过的 <paramref name="target"/> 所有成员,将在映射时被忽略
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
object? IgnoreMapping(T target);
}
/// <summary>
/// 标记一个方法为集合映射方法<br/>
/// 集合映射方法应包含唯一泛型参数 T ,以及唯一参数 <see cref="IEnumerable{T}"/> ,返回类型应该为 <see cref="IEnumerable{T}"/> 的派生类型
/// </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"/>
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
[Obsolete(ErrorCallPlaceholderMethodMessage, true)]
public static TOut MapTo<TOut>(this object source)
{
throw new NotImplementedException();
}
/// <summary>
/// 对象映射 MapTo 占位方法<br/>
/// 生成 需要目标对象 的泛型映射方法,映射到 <typeparamref name="TOut"/>
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
[Obsolete(ErrorCallPlaceholderMethodMessage, true)]
public static TOut MapTo<TOut>(this object source, TOut target)
{
throw new NotImplementedException();
}
/// <summary>
/// 值类型 对象映射 MapTo 占位方法<br/>
/// 生成 需要目标值类型对象 的泛型映射方法,映射到 <typeparamref name="TOut"/>
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <param name="source"></param>
/// <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/>
/// </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 "/>
/// </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 "/>
/// </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 "/>
/// </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}"/>
/// </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}"/>
/// </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}"/>
/// </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}"/>
/// </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}"/>
/// </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}"/>
/// </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();
}
}
}
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Facet