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