欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET core高性能对象转换示例代码

程序员文章站 2022-03-09 21:44:45
前言 net core(开放源代码,跨平台,x-copy可部署等)有许多令人兴奋的方面,其中最值得称赞的就是其性能了。关于对象转换已经有不少*(automapper,t...

前言

net core(开放源代码,跨平台,x-copy可部署等)有许多令人兴奋的方面,其中最值得称赞的就是其性能了。关于对象转换已经有不少*(automapper,tinymapper) .出于项目需要,手动造一个简单*。下面话不多说了,来一起看看详细的介绍吧。

示例代码

g>1.采用静态泛型类缓存,避免了拆箱装箱操作。

2.对于转换对象中有,字段名一样但是类型不一样的类时仍可以用

public static class mapper<tsource, ttarget> where tsource : class where ttarget : class
 {
  public readonly static func<tsource, ttarget> map;

  static mapper()
  {
   if (map == null)
    map = getmap();
  }

  private static func<tsource, ttarget> getmap()
  {
   var sourcetype = typeof(tsource);
   var targettype = typeof(ttarget);

   var parameterexpression = expression.parameter(sourcetype, "p");
   var memberinitexpression = getexpression(parameterexpression, sourcetype, targettype);

   var lambda = expression.lambda<func<tsource, ttarget>>(memberinitexpression, parameterexpression);
   return lambda.compile();
  }

  /// <summary>
  /// 根据转换源和目标获取表达式树
  /// </summary>
  /// <param name="parameterexpression">表达式参数p</param>
  /// <param name="sourcetype">转换源类型</param>
  /// <param name="targettype">转换目标类型</param>
  /// <returns></returns>
  private static memberinitexpression getexpression(expression parameterexpression, type sourcetype, type targettype)
  {
   var memberbindings = new list<memberbinding>();
   foreach (var targetitem in targettype.getproperties().where(x => x.propertytype.ispublic && x.canwrite))
   {
    var sourceitem = sourcetype.getproperty(targetitem.name);

    //判断实体的读写权限
    if (sourceitem == null || !sourceitem.canread || sourceitem.propertytype.isnotpublic)
     continue;

    //标注notmapped特性的属性忽略转换
    if (sourceitem.getcustomattribute<notmappedattribute>() != null)
     continue;

    var propertyexpression = expression.property(parameterexpression, sourceitem);

    //判断都是class 且类型不相同时
    if (targetitem.propertytype.isclass && sourceitem.propertytype.isclass && targetitem.propertytype != sourceitem.propertytype)
    {
     if (targetitem.propertytype != targettype)//防止出现自己引用自己无限递归
     {
      var memberinit = getexpression(propertyexpression, sourceitem.propertytype, targetitem.propertytype);
      memberbindings.add(expression.bind(targetitem, memberinit));
      continue;
     }
    }

    if (targetitem.propertytype != sourceitem.propertytype)
     continue;

    memberbindings.add(expression.bind(targetitem, propertyexpression));
   }
   return expression.memberinit(expression.new(targettype), memberbindings);
  }
 }

3.调用方法如下

 (1)构造样例类

public class a
{
 public int id { get; set; }
 public string name { get; set; }
 public c user { get; set; }
 
 /// <summary>
 /// 标注为notmapped特性时,不转换赋值
 /// </summary>
 [system.componentmodel.dataannotations.schema.notmapped]
 public d usera { get; set; }
 
}
 
public class b
{
 public int id { get; set; }
 public string name { get; set; }
 public d user { get; set; }<br data-filtered="filtered">
 public d usera { get; set; }
}
 
public class c
{
 public int id { get; set; }
 public string name { get; set; }
}
 
public class d
{
 public int id { get; set; }
 public string name { get; set; }
}

  (2) 调用

var a = new a
{
 id = 1,
 name = "张三",
 user = new c
 {
  id = 1,
  name = "李四"
 }
};<br>
b b = mapper<a, b>.map(a);//得到转换结果

4.性能测试

var length = 10000000;
   var lista = new list<a>();
   for (int i = 0; i < length; i++)
   {
    lista.add(new a
    {
     id = i,
     name = "张三",
     user = new c
     {
      id = i,
      name = "李四"
     }
    });
   }

   var sw = stopwatch.startnew();
   for (int i = 0; i < length; i++)
   {
    var item = lista[i];
    var b = new b
    {
     id = item.id,
     name = item.name,
     user = new d
     {
      id = i,
      name = "李四",
     }
    };
   }
   sw.stop();
   console.writeline($"原生的时间:{sw.elapsedmilliseconds}ms");

   //表达式
   mapper<a, b>.map(lista[0]);//预先编译缓存
   sw.restart();
   for (int i = 0; i < length; i++)
   {
    mapper<a, b>.map(lista[i]);
   }
   sw.stop();
   console.writeline($"表达式的时间:{sw.elapsedmilliseconds}ms");

   //automapper
   automapper.mapper.initialize(cfg => cfg.createmap<a, b>());
   sw.restart();
   for (int i = 0; i < length; i++)
   {
    var b = automapper.mapper.map<b>(lista[i]);
   }
   sw.stop();
   console.writeline($"automapper时间:{sw.elapsedmilliseconds}ms");

   //tinymapper
   tinymapper.bind<a, b>();
   sw.restart();
   for (int i = 0; i < length; i++)
   {
    var b = tinymapper.map<b>(lista[i]);
   }
   sw.stop();
   console.writeline($"tinymapper时间:{sw.elapsedmilliseconds}ms");

   console.readline();

5. 1000万数据不带子类集结果

.NET core高性能对象转换示例代码

6. 1000万数据带子类集结果 

.NET core高性能对象转换示例代码

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。