RSCG – MagicMap
RSCG – MagicMap
name | MagicMap |
nuget | https://www.nuget.org/packages/MagicMap/ |
link | https://github.com/bramerdaniel/MagicMap |
author | Bramer Daniel |
Auto mapping
This is how you can use MagicMap .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="MagicMap" Version="1.0.0-alpha.10" OutputItemType="Analyzer" /> </ItemGroup> </Project>
The code that you will use is
// See https://aka.ms/new-console-template for more information using mapperlyDemo; var p=new Person(); p.FirstName = "Andrei"; p.LastName = "Ignat"; PersonDTO dto = p.ToPersonDTO(); Console.WriteLine(dto.FullName);
public class Person { public int ID { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } }
using MagicMap; namespace mapperlyDemo; [TypeMapper(typeof(Person), typeof(PersonDTO))] internal partial class PersonMapper { } public class PersonDTO { public int ID { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public string FullName { get { return FirstName + " " + LastName; } } }
The code that is generated is
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace mapperlyDemo { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] partial class PersonMapper { /// <summary> /// The default singleton instance of the generated type mapper. /// To customize the creation of the default mapper, just implement this property in the defining partial part. /// </summary> public static PersonMapper Default { get; } = new PersonMapper(); /// <summary>Maps all properties of the <see cref = "source"/> to the properties of the <see cref = "target"/></summary> public void Map(global::Person source, global::mapperlyDemo.PersonDTO target) { target.ID = source.ID; target.FirstName = source.FirstName; target.LastName = source.LastName; MapOverride(source, target); } internal global::mapperlyDemo.PersonDTO MapFrom(global::Person source) { var target = Default is MagicMap.ITypeFactory<global::mapperlyDemo.PersonDTO, global::Person> factory ? factory.Create(source) : new global::mapperlyDemo.PersonDTO(); Default.Map(source, target); return target; } /// <summary>Maps all properties of the <see cref = "source"/> to the properties of the <see cref = "target"/></summary> public void Map(global::mapperlyDemo.PersonDTO source, global::Person target) { target.ID = source.ID; target.FirstName = source.FirstName; target.LastName = source.LastName; MapOverride(source, target); } internal global::Person MapFrom(global::mapperlyDemo.PersonDTO source) { var target = Default is MagicMap.ITypeFactory<global::Person, global::mapperlyDemo.PersonDTO> factory ? factory.Create(source) : new global::Person(); Default.Map(source, target); return target; } /// <summary>Implement this method, to map the properties the mapper could not handle for any reason.</summary> partial void MapOverride(global::Person source, global::mapperlyDemo.PersonDTO target); /// <summary>Implement this method, to map the properties the mapper could not handle for any reason.</summary> partial void MapOverride(global::mapperlyDemo.PersonDTO source, global::Person target); } }
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace mapperlyDemo { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] internal static partial class PersonMapperExtensions { /// <summary> /// The instance of the <see cref = "PersonMapper"/> all extension methods use. /// You can customize this by implementing this property in your own partial implementation of the extensions class. /// </summary> private static global::mapperlyDemo.PersonMapper Mapper => global::mapperlyDemo.PersonMapper.Default; internal static global::mapperlyDemo.PersonDTO ToPersonDTO(this global::Person person) { if (person == null) throw new global::System.ArgumentNullException(nameof(person)); var result = Mapper is MagicMap.ITypeFactory<global::mapperlyDemo.PersonDTO, global::Person> factory ? factory.Create(person) : new global::mapperlyDemo.PersonDTO(); Mapper.Map(person, result); return result; } internal static global::Person ToPerson(this global::mapperlyDemo.PersonDTO personDTO) { if (personDTO == null) throw new global::System.ArgumentNullException(nameof(personDTO)); var result = Mapper is MagicMap.ITypeFactory<global::Person, global::mapperlyDemo.PersonDTO> factory ? factory.Create(personDTO) : new global::Person(); Mapper.Map(personDTO, result); return result; } } }
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace MagicMap { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)] /// <summary>Attribute that can be used mark a method as mapping method for a specific source property</summary> internal sealed class PropertyMapperAttribute : global::System.Attribute { /// <summary>Marks a function as a custom mapping method for the specified property.</summary> public PropertyMapperAttribute(global::System.Type targetType, string targetName) : this(targetType, targetName, targetName) { } /// <summary>Marks a function as a custom mapping method for the specified property.</summary> public PropertyMapperAttribute(global::System.Type targetType, string targetName, string sourceName) { TargetType = targetType ?? throw new global::System.ArgumentNullException(nameof(targetType)); TargetName = targetName ?? throw new global::System.ArgumentNullException(nameof(targetName)); SourceName = sourceName ?? throw new global::System.ArgumentNullException(nameof(sourceName)); } /// <summary>Gets the type of the target class, the mapper should be used for.</summary> public global::System.Type TargetType { get; } /// <summary>Gets the name of the property that should be mapped to.</summary> public string TargetName { get; } /// <summary>Gets the name of the source property that should be mapped from.</summary> public string SourceName { get; } } }
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace MagicMap { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] [global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true, Inherited = false)] /// <summary>Attribute that can be used to map a specific property from the left to the right object by their names</summary> internal sealed class PropertyMappingAttribute : global::System.Attribute { public PropertyMappingAttribute(string leftName, string rightName) { LeftName = leftName ?? throw new global::System.ArgumentNullException(nameof(leftName)); RightName = rightName ?? throw new global::System.ArgumentNullException(nameof(rightName)); } /// <summary>Gets the name of the left property.</summary> public string LeftName { get; } /// <summary>Gets the name of the right property.</summary> public string RightName { get; } /// <summary>Gets or sets a value indicating that the properties should be ignored for mapping generation.</summary> public bool Ignore{ get; set; } } }
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace MagicMap { [global::System.Runtime.CompilerServices.CompilerGenerated] internal interface ITypeFactory<TTarget, TSource> where TTarget : class { /// <summary>Created an instance of the type TTarget, that is used for a mapping.</summary> TTarget Create(TSource source); } }
//------------------------------------------------ // <auto-generated> // Generated by the MagicMap source generator // </auto-generated> //------------------------------------------------ namespace MagicMap { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] [global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = false, Inherited = false)] internal sealed class TypeMapperAttribute : global::System.Attribute { public TypeMapperAttribute(global::System.Type left, global::System.Type right) { Left = left ?? throw new global::System.ArgumentNullException(nameof(left)); Right = right ?? throw new global::System.ArgumentNullException(nameof(right)); } /// <summary>Gets the left type.</summary> public global::System.Type Left { get; } /// <summary>Gets the right type.</summary> public global::System.Type Right { get; } /// <summary>Gets or sets the <see cref="GenerationMode"/>.</summary> public GeneratorMode Mode { get; set; } = GeneratorMode.TwoWay; /// <summary>Gets or sets a flag, indicating if the source generator should generate partial methods /// for properties he can not map, to enforce that they are handled by the user.</summary> public bool ForceMappings { get; set; } = false; } /// <summary>Enum for configuring the source generator mode</summary> internal enum GeneratorMode { /// <summary>Mappers are generated for both ways, from left to right and back</summary> TwoWay, /// <summary>Only a mapper from left to right typ is generated</summary> LeftToRight, /// <summary>Only a mapper from right to left typ is generated</summary> RightToLeft } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/MagicMap
Leave a Reply