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