AutoMapper 入门
- 浅入 AutoMapper
- AutoMapper 基本使用
- 映射配置
- 映射检查
- 性能
- Profile 配置
- 依赖注入
- 表达式与 DTO
浅入 AutoMapper
假如两个如下类型:
public class TestA
{
public int A { get; set; }
public string B { get; set; }
// 剩下 99 个字段省略
}
public class TestB
{
public int A { get; set; }
public string B { get; set; }
// 剩下 99 个字段省略
}
我们可以通过 AutoMapper 快速将 TestA 中所有字段的值复制一份到 TestB 中。
创建 TestA 到 TestB 的映射配置:
MapperConfiguration configuration = new MapperConfiguration(cfg =>
{
// TestA -> TestB
cfg.CreateMap();
});
创建映射器:
IMapper mapper = configuration.CreateMapper();
使用 .Map()
方法将 TestA 中字段的值复制到 TestB 中。
TestA a = new TestA();
TestB b = mapper.Map(a);
映射配置
假如 TestA 有的字段 TestB 没有,则不复制;TestB 有的字段 TestA 中没有,则此字段不做处理(初始化值)。
默认情况,TestA 跟 TestB 中的字段不太一致的话,可能有些地方容易造成忽略,开发者可以使用检查器去检查。
只需要在定义 MapperConfiguration
以及映射关系后,调用:
configuration.AssertConfigurationIsValid();
这个检查方法,只应在 Debug 下使用。
当映射没有被覆盖时
你可以在 TestB 中增加一个 D 字段,然后启动程序,会提示:
AutoMapper.AutoMapperConfigurationException
因为 TestB 中的 D 字段,没有相应的映射。这样,当我们在编写映射关系时,就可以避免漏值的情况。
性能
除了 MapperConfiguration 外,我们还可以使用继承 Profile 的方式定义映射配置,实现更小粒度的控制以及模块化,ABP 框架中正是推荐了 AutoMapper 的此种方式,配合模块化。
示例如下:
public class MyProfile : Profile
{
public MyProfile()
{
// 这里就不赘述了
base.CreateMap().ForMember(... ...);
}
}
如果我们使用 ABP,那么每个模块都可以定义一个 Profiles 文件夹,在里面定义一些 Profile 规则。
一种映射定义一个 Profile 类?这样太浪费空间了;一个模块定义一个 Profile 类?这样太杂了。不同的程序有自己的架构,按照项目架构选择 Profile 的粒度就好。
依赖注入
AutoMapper 有着不少拓展,这里笔者介绍一下 AutoMapper.Extensions.ExpressionMapping,在 Nuget 里面可以搜索到。
AutoMapper.Extensions.ExpressionMapping
这个拓展实现了大量的表达式树查询,这个库实现了 IMapper 拓展。
假如:
public class DataDBContext : DbContext
{
public DbSet TestA { get; set; }
}
... ...
DataDBContext data = ... ...
配置:
private static readonly MapperConfiguration configuration = new MapperConfiguration(cfg =>
{
cfg.AddExpressionMapping();
cfg.CreateMap();
});
假如,你要实现过滤功能:
// It's of no use
Expressionbool>> filter = item => item.A > 0;
var f = mapper.MapExpressionbool>>>(filter);
var someA = data.AsQueryable().Where(f); // data is _context or conllection
当然,这段代码没有任何用处。
你可以实现自定义的拓展方法、表达式树,更加便利地对 DTO 进行操作。
下面是示例:
public static class Test
{
// It's of no use
//public static TB ToType(this TA a, IMapper mapper, Expression> func)
//{
// //Func f1 = mapper.MapExpression>>(func).Compile();
// //TB result = f1(a);
// return mapper.MapExpression>>(func).Compile()(a);
//}
public static IEnumerable<TB> ToType<TA, TB>(this IEnumerable list, IMapper mapper, Expression> func )
{
var one = mapper.MapExpression>>(func).Compile();
List bList = new List();
foreach (var item in list)
{
bList.Add(one(item));
}
return bList;
}
}
当你查询时,可以这样使用这个拓展:
_ = _context.TestA.ToArray().ToType(mapper, item => mapper.Map(item));
出处:https://www.cnblogs.com/whuanle/p/14160944.html