WAutoMapper - qidot/YunstpNetCore GitHub Wiki

通过表达式拷贝变量

本文介绍了如何快速的复制一个类到另外一个类

在java的spring框架中经常会用到 BeanUtils.CopyProperties(from,target); 来实现目标类的快速赋值

在c#中,也有相对应的功能包,如:

  • AutoMapper
  • TinyMapper

在项目中呢,我参考了网上的相关资料后,改动成表达式来实现这个功能:

先看下通常情况下的赋值:

var a = new DtoA();
var b = new EntityA();
b.Id = a.Id;
b.Name = a.Name;
//或者是
var b = new EntityA{
  Id = a.Id,
  Name = a.Name
};

其实想法很简单,就是想少写一点代码,怎么实现呢

这里需要用到: lamda 来帮助我们实现了

定义WAutoMapper

详细请参见:

WAutoMapper.cs 复制帮助类

TestWorker.cs 测试用的实体

TestWorkerQueryDTO.cs 测试用的DTO

用法

我们分别用copy法与手工实例来进行测试,看看到底有什么区别

public IActionResult CopyExample([FromBody]TestWorkerQueryDTO testWorkerDTO)
{
     Console.WriteLine($"dto=====>{testWorkerDTO.toJson()}");
     Console.WriteLine($"复制实例");
     var model = WAutoMapper<TestWorkerQueryDTO, TestWorker>.Map(testWorkerDTO);
     Console.WriteLine($"model====>{model.toJson()}");
     Console.WriteLine($"正常实例");
     var model2 = new TestWorker
     {
        id = (int)testWorkerDTO.id,
        createTime = testWorkerDTO.createTime,
        name = testWorkerDTO.name,
        age = testWorkerDTO.age
     };

     Console.WriteLine($"model====>{model2.toJson()}");
     return Ok("ok");
}

看下实际的输出的表达式

image-20190909102118855

发现TA其实就是用了

var b = new EntityA{
  Id = a.Id,
  Name = a.Name
};

int? 与 int 赋值

在.net中值类型是不能为空的,都会给上默认值,比如: int,long,DateTime等

刚开始的时候发现int?与int是不能赋值的,怎么处理呢,要判定一下

if (targetItem.PropertyType != sourceItem.PropertyType) {
   //Nullable处理::::::System.Int32,System.Nullable`1[System.Int32]
   //int与int? 或 int?与int
   var targetTypeStr = targetItem.PropertyType.ToString();
   var sourceTypeStr = sourceItem.PropertyType.ToString();
   bool isSourceNullable = sourceTypeStr.StartsWith("System.Nullable", StringComparison.Ordinal)
                        && sourceTypeStr.IndexOf(targetTypeStr, StringComparison.Ordinal) >= 0;
   bool isTargetNullable = targetTypeStr.StartsWith("System.Nullable", StringComparison.Ordinal)
                        &&
                        targetTypeStr.IndexOf(sourceTypeStr, StringComparison.Ordinal) >= 0;
   if (isSourceNullable || isTargetNullable) {
       memberBindings.Add(Expression.Bind(targetItem, Expression.Convert(propertyExpression, targetItem.PropertyType)));
   } 
   continue;
}

我们先注释掉这一段,来看下输出,你会发现相关差异

image-20190909103115357

表达式变短了,缺少了相关属性,那是因为 int? 与 int的 type是不一致的,一个是Nullable<System.Int32> 一个是Int32这2个不等,所以被跳过

扩展

关于 int,long 数值大小类型的转换呢? 这个代码没有写,可能会遇到此类情景

效率对比

请看文章::: https://www.cnblogs.com/castyuan/p/9285101.html

具体测试我没有做,感兴趣的同学可以自己去实践一下。