MagicMap by Bramer Daniel
Nuget / site data
Details
Info
info
Name: MagicMap
Helper utility for generating type mapper classes and more
Author: Bramer Daniel
NuGet: https://www.nuget.org/packages/MagicMap/
You can find more details at https://github.com/bramerdaniel/MagicMap
Original Readme
note
MagicMap
SourceGenerator based package for generating boilerplate code like object mappers
This is still under construction
Mapping code from one class to another
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class PersonModel
{
public string Name { get; set; }
public int Age { get; set; }
}
The required code to write
[TypeMapper(typeof(Person), typeof(PersonModel))]
internal partial class PersonMapper { }
Usage
var source = new Person { Name = "Peter", Age = 34 };
var model = source.ToPersonModel();
About
note
Auto mapping
How to use
Example ( source csproj, source files )
- CSharp Project
- Program.cs
- Person.cs
- PersonDTO.cs
This is the CSharp Project that references MagicMap
<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>
This is the use of MagicMap in Program.cs
// 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);
This is the use of MagicMap in Person.cs
public class Person
{
public int ID { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
This is the use of MagicMap in PersonDTO.cs
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;
}
}
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- PersonMapper.generated.cs
- PersonMapperExtensions.generated.cs
- PropertyMapperAttribute.generated.cs
- PropertyMappingAttribute.generated.cs
- TypeFactory.generated.cs
- TypeMapperAttribute.generated.cs
//------------------------------------------------
// <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
}
}
Usefull
Download Example (.NET C# )
Share MagicMap
https://ignatandrei.github.io/RSCG_Examples/v2/docs/MagicMap