对象有集合mapper映射_HigLabo.Mapper,用表达式树在10天内创建世界上最快的对象映射器...

对象有集合mapper映射

介绍 (Introduction)

Four years ago, I created the initial version of object mapper with IL code. Just a few weeks ago, I decided to reimplement HigLabo.Mapper with Expression Tree and achieve huge performance improvement. It scored fastest in the world currently. You can see my 10 days commit log at https://github.com/higty/higlabo.netstandard/tree/master/HigLabo.Mapper.

四年前,我用IL代码创建了对象映射器的初始版本。 就在几周前,我决定用Expression Tree重新实现HigLabo.Mapper并实现巨大的性能改进。 它目前在世界上得分最高。 您可以在https://github.com/higty/higlabo.netstandard/tree/master/HigLabo.Mapper上查看我的10天提交日志。

I share my code and library to contribute to the C# and .NET community.

我共享我的代码和库,以为C#和.NET社区做出贡献。

The source code can be found at https://github.com/higty/higlabo/tree/master/NetStandard/HigLabo.Mapper.

可以在https://github.com/higty/higlabo/tree/master/NetStandard/HigLabo.Mapper中找到源代码。

You can use from Nuget.

您可以从Nuget使用。

HigLabo.Mapper (version 3.0.x.x)

HigLabo.Mapper (版本3.0.xx)

背景 (Background)

Now a days, whether you are a developer of Web, Desktop, Mobile, you may use some of POCO, DTO object. And you must transfer property value from object to object. Object mapper is useful for this situation. This time, the goal of my reimplementation is as listed below:

如今,无论您是Web,Desktop,Mobile的开发人员,都可以使用POCO,DTO对象。 而且,您必须在对象之间传递属性值。 对象映射器对于这种情况很有用。 这次,我重新实现的目标如下所示:

  1. Fastest in the world

    世界上最快
  2. Zero configuration for productivity

    零配置提高生产力
  3. Full customization for various usecase

    全面定制各种用例
  4. Multiple mapping rule for an application

    应用程序的多重映射规则

如何使用? (How to Use?)

You can get HigLabo.Mapper (version 3.0.0 or later) from Nuget package. (Old HigLabo.Mapper is moved to HigLabo.Mapper.ObjectMapConfig package.)

您可以从Nuget包中获取HigLabo.Mapper (版本3.0.0或更高版本)。 (旧的HigLabo.Mapper已移至HigLabo.Mapper.ObjectMapConfig package 。)

Add using directive in your application:

在您的应用程序中添加using指令:

using HigLabo.Core;

Now you can use Map extension method like this:

现在您可以使用Map扩展方法,如下所示:

var a1 = new Address(); //your POCO class.
var a2 = a1.Map(new Address());

HigLabo.Mapper supports Dictionary to Object mapping.

HigLabo.Mapper支持字典到对象的映射。

var d = new Dictionary<String, String>(); 
d["Name"] = "Bill";
var person = d.Map(new Person());
//person.Name is "Bill"

Object to Dictionary also supported.

还支持对象到字典。

var p = new Person(); 
p.Name = "Bill";
var d = p.Map(new Dictionary<String, String>);
//d["Name"] is "Bill"

I design HigLabo.Mapper easy to use.

我设计的HigLabo.Mapper易于使用。

与其他映射器的比较 (Comparison to Other Mappers)

In this chapter, I will explain the difference to other mapper libraries. This is a summary of comparison.

在本章中,我将解释与其他映射器库的区别。 这是比较的摘要。

  1. Performance

    性能
  2. Initial Configuration

    初始配置
  3. Customization

    客制化
  4. Multiple Settings

    多种设定

性能!!! (Performance!!!)

It is important for mapper library because it has a tendency to be used in deeper place like inside loop. The summary of performance test is here.

这对于mapper库很重要,因为它倾向于在更深的地方(如内部循环)使用。 性能测试的摘要在这里。

  • 3x-4x faster than AutoMapper (for POCO that does not have collection property)

    比AutoMapper快3到4倍 (对于没有收集属性的POCO)

  • 10%-20% faster than Mapster (for POCO that does not have collection property)

    比Mapster快10%-20% (对于没有收集属性的POCO)

  • 7x-10x faster than AgileMapper, FastMapper, TinyMapper (for POCO that does not have collection property) 

    比AgileMapper,FastMapper和TinyMapper快7到10倍 (适用于没有收集属性的POCO)

  • 3x faster than AutoMapper (for POCO that has collection property)

    比AutoMapper快3倍 (对于具有收集属性的POCO)

  • 10x faster than Mapster (for POCO that has collection property)

    比Mapster快10倍(对于具有收藏属性的POCO)

  • 10x-20x faster than AgileMapper, FastMapper, TinyMapper (for POCO that has collection property)

    比AgileMapper,FastMapper和TinyMapper快10到20倍 (对于具有收集属性的POCO)

Here is a performance test result with BenchmarkDotNet. HigLaboObjectMapper_XXXX is the result of  new HigLabo.Mapper.

这是BenchmarkDotNet的性能测试结果。 HigLaboObjectMapper_XXXX是新HigLabo.Mapper的结果。

Image 1

Here is a class that is used for performance test.

这是用于性能测试的类。

public class Address
{
    public int Id { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public AddressType AddressType { get; set; }
}

public class AddressDTO
{
    public int Id { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public AddressType AddressType { get; set; } = AddressType.House;
}
public struct GpsPosition
{
    public double Latitude { get; private set; }
    public double Longitude { get; private set; }

    public GpsPosition(double latitude, double longitude)
    {
        this.Latitude = latitude;
        this.Longitude = longitude;
    }
}

public class Customer
{
    public Int32? Id { get; set; }
    public String Name { get; set; }
    public Address Address { get; set; }
    public Address HomeAddress { get; set; }
    public Address[] AddressList { get; set; }
    public IEnumerable<Address> WorkAddressList { get; set; }
}

public class CustomerDTO
{
    public Int32? Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
    public AddressDTO HomeAddress { get; set; }
    public AddressDTO[] AddressList { get; set; }
    public List<AddressDTO> WorkAddressList { get; set; }
    public String AddressCity { get; set; }
}


I tested 4 types of mapping like this:

我测试了4种类型的映射,如下所示:

1. POCO class without collection property to same class.
XXX.Map(new Address(), new Address())

2. POCO class without collection property to other class.
XXX.Map(new Address(), new AddressDTO())

3. POCO class that has collection property map to same class.
XXX.Map(new Customer(), new Customer())

4. POCO class that has collection property map to other class.
XXX.Map(new Customer(), new CustomerDTO());

As you can see, all 4 cases HigLabo.Mapper is fastest.

如您所见,所有4种情况的HigLabo.Mapper都是最快的。

You can see the entire test code at https://github.com/higty/higlabo/tree/master/NetStandard/HigLabo.Test/HigLabo.Mapper.PerformanceTest.

您可以在https://github.com/higty/higlabo/tree/master/NetStandard/HigLabo.Test/HigLabo.Mapper.PerformanceTest查看完整的测试代码。

初始配置 (Initial Configuration)

Some of Mapper requires initial configuration like this:

一些Mapper需要这样的初始配置:

var configuration = new AutoMapper.MapperConfiguration(config => {
    config.CreateMap<Building, Building>();
    config.CreateMap<TreeNode, TreeNode>();
});

This is AutoMapper configuration code. If you have thousands of classes to map with, it is quite boring to create this mapping configuration code. TinyMapper also requires configuration.

这是AutoMapper配置代码。 如果您要映射成千上万个类,那么创建此映射配置代码将很无聊。 TinyMapper也需要配置。

TinyMapper.Bind<Park, Park>();
TinyMapper.Bind<Customer, CustomerDTO>();
TinyMapper.Bind<Dictionary<String, String>, Building>();

HigLabo.Mapper does not require any configuration. You can use it out of the box.

HigLabo.Mapper不需要任何配置。 您可以直接使用它。

客制化 (Customization)

Sometimes, you want to customize the mapping rule against your POCO object. AutoMapper is so complicated to customize mapping rule. I compare AutoMapper and HigLabo.Mapper with example of this page.

有时,您想针对POCO对象自定义映射规则。 自定义映射规则非常复杂。 我将AutoMapperHigLabo.Mapper与该页面的示例进行比较。

https://stackoverflow.com/questions/50964757/delegating-member-mapping-to-child-object-with-automapper

https://stackoverflow.com/questions/50964757/delegating-member-mapping-to-child-object-with-automapper

class Source {
  public int Id {get;set;}
  public int UseThisInt {get;set;}
  public InnerType Inner {get;set;}
  // other properties that the Destination class is not interested in
}
class InnerType {
  public int Id {get;set;}
  public int Height {get;set;}
  // more inner properties
}
class Destination {
  public int Id {get;set;}
  public int UseThisInt {get;set;}
  public int Height {get;set;}
  // more inner properties that should map to InnerType
}

//So many configuration and complicated....
Mapper.Initialize(cfg => {
    cfg.CreateMap<source, destination="">();
    cfg.CreateMap<innertype, destination="">();
});
var dest = Mapper.Map<destination>(src);
Mapper.Map(src.Inner, dest);
Mapper.Initialize(cfg => {
        cfg.CreateMap<source, destination="">()AfterMap
                     ((src, dest) => Mapper.Map(src.Inner, dest));
        cfg.CreateMap<innertype, destination="">();
    });
var dest = Mapper.Map<destination>(src);

If you use AutoMapper, you must know about the AutoMapper library like Mapper.Initialize, ForMember, CreateMap, AfterMap, etc.

如果使用AutoMapper ,则必须了解AutoMapper库,例如Mapper.InitializeForMemberCreateMapAfterMap等。

HigLabo.Mapper can customize like this:

HigLabo.Mapper可以像这样自定义:

c.AddPostAction<Source, Destination>((s, d) =>
{
    d.Id = s.Inner.Id;
    //Set Inner object property to Destination object     
    s.Inner.Map(d); 
});

HigLabo.Mapper simply calls this lambda after mapping completed when you call Map method. So, you can overwrite default mapping rule.

当您调用Map方法时,映射完成后, HigLabo.Mapper简单地调用此lambda。 因此,您可以覆盖默认映射规则。

You can completely replace mapping rule with ReplaceMap method like this:

您可以使用ReplaceMap方法完全替换映射规则,如下所示:

c.ReplaceMap<Source, Destination>((s, d) =>
{
    //Set all map with your own.
    d.Id = s.Inner.Id;
    //Set Inner object property to Destination object
    s.Inner.Map(d);
});
//You can call Map method.
var source = new Source();
var destination = new Destination();
source.Map(distination); //Above lambda will be called.

It is simple and no additional knowledge is required. You can only know about C# lambda that you already use.

它很简单,不需要其他知识。 您只能知道已经使用的C#lambda。

You can easily add convert logic.

您可以轻松添加转换逻辑。

c.AddPostAction<Person, PersonVM>((s, d) =>
{
    d.BMI = CalculateBMI(s.Height, s.Weight);
});

You can also use conditional property map.

您还可以使用条件属性映射。

c.AddPostAction<Employee, EmployeeVM>((s, d) =>
{
    if (s.EmployeeType == EmployeeType.Contract)
    {
        d.Property1 = someValue1;
    }
    else
    {
        d.Property1 = someValue2;
    }
});

Another advantage of this design is that you can easily debug to your code. You can set break point on lambda inside AddPostAction, ReplaceMap method.

这种设计的另一个优点是,您可以轻松地调试代码。 您可以在AddPostActionReplaceMap方法内的lambda上设置断点。

You can also customize property mapping rule like this:

您还可以像这样自定义属性映射规则:

class Person
{
    public string Name { get; set; }
    public string Position_Name { get; set; }
}
class PersonModel
{
    public string Name { get; set; }
    public string PositionName { get; set; }
}

var mapper = HigLabo.Core.ObjectMapper.D
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值