当前位置:网站首页>4. Object mapping Mapster

4. Object mapping Mapster

2022-07-05 06:14:00 Masa technical team

Preface

We often encounter object mapping in projects , Such as Model and Dto Mapping between , Or a deep copy of an object , We need to realize these by ourselves . here , There will be a lot of code for initializing objects in the project , The code is pretty boring to write , Is there any way to reduce our workload , So that we can spend time on business functions ?

at present ,.Net Object mapping framework in , Powerful and excellent object mapping frameworks already exist , The most used ones are :

Speaking of the object mapping framework , What people think of most is AutoMapper, Maybe a lot of people Mapster Never heard of it , But there's no denying it Mapster It is really a good object mapping framework , However, due to the lack of Chinese documents , As a result, the popularity in China is not very high , Today we will introduce Mapster What functions are provided , How to use it in a project ,Masa Provided Mapster What else has been done ?

Mapster brief introduction

Mapster It's a simple to use , Powerful object mapping framework , since 2014 It's past since the year of open source 8 A year , Up to now ,github I already have 2.6k Of star, And keep it every year 3 Distribution frequency of times , Its function and AutoMapper similar , Provide object to object mapping 、 And support IQueryable Mapping to objects , And AutoMapper comparison , Better performance in terms of speed and memory usage , You can only use 1/3 In the case of memory 4 Times performance improvement , Let's take a look at Mapster How to use ?

preparation

  • Create a new console project Assignment.Mapster, And install Mapster

    dotnet add package Mapster --version 7.3.0

Map to new object

  1. The new class UserDto

    public class UserDto{    public int Id { get; set; }    public string Name { get; set; }    public uint Gender { get; set; }    public DateTime BirthDay { get; set; }}
  2. Create a new anonymous object , As the source of the object to be converted

    var user = new{    Id = 1,    Name = "Tom",    Gender = 1,    BirthDay = DateTime.Parse("2002-01-01")};
  3. take user The source object is mapped to the target object (UserDto)

    var userDto = user.Adapt<UserDto>();Console.WriteLine($" Map to new object ,Name: {userDto.Name}");

Run the console program to verify that the conversion is successful :  Map to new object

data type

In addition to providing object-to-object mapping , It also supports data type conversion , Such as :

Basic types

  • Provide the function of type mapping , similar Convert.ChangeType()

    string res = "123";decimal i = res.Adapt<decimal>(); //equal to (decimal)123;Console.WriteLine($" The result is :{i == int.Parse(res)}");

Run the console program :  Basic type conversion

Enumeration type

  • Map enumerations to numeric types , It also supports string to enumeration and enumeration to string mapping , Than .NET The default implementation of is twice as fast

    var fileMode = "Create, Open".Adapt<FileMode>();// be equal to  FileMode.Create | FileMode.OpenConsole.WriteLine($" The result of enumeration type conversion is :{fileMode == (FileMode.Create | FileMode.Open)}");

Run the console program to verify that the conversion is successful :  Basic type conversion

Queryable Expand

Mapster Provides Queryable An extension of , Used to implement DbContext On demand lookup for , for example :

  1. The new class UserDbContext

    using Assignment.Mapster.Domain;using Microsoft.EntityFrameworkCore;namespace Assignment.Mapster.Infrastructure;public class UserDbContext : DbContext{    public DbSet<User> User { get; set; }    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)    {        var dataBaseName = Guid.NewGuid().ToString();        optionsBuilder.UseInMemoryDatabase(dataBaseName);// Use memory database , Convenient test     }}
  2. The new class User

    public class User{    public int Id { get; set; }    public string Name { get; set; }    public uint Gender { get; set; }    public DateTime BirthDay { get; set; }    public DateTime CreationTime { get; set; }    public User()    {        CreationTime = DateTime.Now;    }}
  3. Using a Queryable Extension method of ProjectToType

    using (var dbContext = new UserDbContext()){    dbContext.Database.EnsureCreated();    dbContext.User.Add(new User()    {        Id = 1,        Name = "Tom",        Gender = 1,        BirthDay = DateTime.Parse("2002-01-01")    });    dbContext.SaveChanges();    var userItemList = dbContext.User.ProjectToType<UserDto>().ToList();}

Run the console program to verify that the conversion is successful : Queryable Expand

besides ,Mapster Pre mapping is also provided / post-processing , Copy and merge and mapping configuration nesting support , Details can be viewed file , since Mapster Already so powerful , Then I can use it directly , Why even use Masa Provided Mapper Well ?

What is? Masa.Contrib.Data.Mapping.Mapster?

Masa.Contrib.Data.Mapping.Mapster Is based on Mapster An object to object mapper for , And in the original Mapster Add auto get and use best constructor mapping based on , Support nested mapping , Reduce the workload of mapping .

Mapping rule

  • When the target object does not have a constructor : Use an empty constructor , Mapping to fields and attributes .

  • Multiple constructors exist for the target object : Get the best constructor mapping

    Best constructor : The number of constructor parameters of the target object is found in descending order , The parameter names are consistent ( Case insensitive ) And the parameter type is consistent with the source object attribute

preparation

  • Create a new console project Assignment.Masa.Mapster, And install Masa.Contrib.Data.Mapping.Mapster,Microsoft.Extensions.DependencyInjection

    dotnet add package Masa.Contrib.Data.Mapping.Mapster --version 0.4.0-rc.4dotnet add package Microsoft.Extensions.DependencyInjection --version 6.0.0
  1. The new class OrderItem

    public class OrderItem{    public string Name { get; set; }    public decimal Price { get; set; }    public int Number { get; set; }    public OrderItem(string name, decimal price) : this(name, price, 1)    {    }    public OrderItem(string name, decimal price, int number)    {        Name = name;        Price = price;        Number = number;    }}
  2. The new class Order

    public class Order{    public string Name { get; set; }    public decimal TotalPrice { get; set; }    public List<OrderItem> OrderItems { get; set; }    public Order(string name)    {        Name = name;    }    public Order(string name, OrderItem orderItem) : this(name)    {        OrderItems = new List<OrderItem> { orderItem };        TotalPrice = OrderItems.Sum(item => item.Price * item.Number);    }}
  3. Modify the class Program

    using Assignment.Masa.Mapster.Domain.Aggregate;using Masa.BuildingBlocks.Data.Mapping;using Masa.Contrib.Data.Mapping.Mapster;using Microsoft.Extensions.DependencyInjection;Console.WriteLine("Hello Masa Mapster!");IServiceCollection services = new ServiceCollection();services.AddMapping();var request = new{    Name = "Teach you to learn Dapr ……",    OrderItem = new OrderItem("Teach you to learn Dapr hand by hand", 49.9m)};var serviceProvider = services.BuildServiceProvider();var mapper = serviceProvider.GetRequiredService<IMapper>();var order = mapper.Map<Order>(request);Console.WriteLine($"{nameof(Order.TotalPrice)} is {order.TotalPrice}");// Console output 49.9Console.ReadKey();

If the conversion is successful ,TotalPrice The value should be 49.9, Then we run the console program to verify whether the conversion is successful :

Mapping.Mapster

How to achieve

We mentioned above Masa.Contrib.Data.Mapping.Mapster You can automatically get and use the best constructor mapping , And then complete the object to object mapping , So how does it come true ? Will it affect the performance ?

It is used to automatically obtain and use the best constructor mapping Mapster The function of constructor mapping provided by , By specifying the constructor , Complete object to object mapping .

see file

summary

at present Masa.Contrib.Data.Mapping.Mapster Its function is relatively weak , The current version is similar to Mapster It only adds a function of automatically obtaining and using the best constructor , Let's easily complete the mapping when facing a class that has no empty constructor and has multiple constructors , There is no need to write an extra line of code .

But I think Masa Version of Mapping The biggest benefit is that the project depends on BuildingBlocks Under the IMapper, instead of Mapster, This makes our project separate from the specific mapper implementation , If we are asked that the project must use AutoMapper, Just implement AutoMapper Version of IMapper that will do , No need to change too many business codes , Just replace the referenced package , This is also BuildingBlocks The charm of

Source code of this chapter

Assignment04

https://github.com/zhenlei520/MasaFramework.Practice

Open source address

MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks

MASA.Contrib:https://github.com/masastack/MASA.Contrib

MASA.Utils:https://github.com/masastack/MASA.Utils

MASA.EShop:https://github.com/masalabs/MASA.EShop

MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor

If you treat our MASA Framework Interested in , Whether it's code contribution 、 Use 、 carry Issue, Welcome to contact us

16373211753064.png

原网站

版权声明
本文为[Masa technical team]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050609476592.html