百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

简单的AutoMapper使用演示

ztj100 2025-01-02 20:34 22 浏览 0 评论

将网站臻于至善,将服务推向极致,为客户全心投入,为信赖竭诚付出,此乃我每日的工作常态。所从事的是生意,所结交的是朋友,没有巧言令色,唯有赤诚真心。倘若有需求,敬请随时来找我,诚盼您的莅临。

AutoMapper的作用

在深入研究AutoMapper的源码之前,我们先来了解一下AutoMapper的作用。根据官网的解释,AutoMapper是一个简洁的库,旨在解决一个看似复杂的问题:摆脱手动编写将一个对象映射到另一个对象的代码。

简单的AutoMapper使用演示

首先,我们通过一个简单的示例来展示如何使用AutoMapper。

var config = new MapperConfiguration(cfg =>
cfg.CreateMap<ModelObject, ModelDto>()
);
var mapper1 = config.CreateMapper();
var mode;= mapper1.Map<ModelObject>(new ModelDto{ Name= 1 });

构造函数中的配置

在这段代码中,默认会创建一个MapperConfiguration对象,并传入一个包含映射关系的Action。当MapperConfiguration对象被创建时,会执行其构造函数。


public MapperConfiguration(MapperConfigurationExpression configurationExpression)
{
_mappers = configurationExpression.Mappers.ToArray();
_resolvedMaps = new LockingConcurrentDictionary<TypePair, TypeMap>(GetTypeMap);
_executionPlans = new LockingConcurrentDictionary<MapRequest, Delegate>(CompileExecutionPlan);
_validator = new ConfigurationValidator(this, configurationExpression);
ExpressionBuilder = new ExpressionBuilder(this);

ServiceCtor = configurationExpression.ServiceCtor;
EnableNullPropagationForQueryMapping = configurationExpression.EnableNullPropagationForQueryMapping ?? false;
MaxExecutionPlanDepth = configurationExpression.Advanced.MaxExecutionPlanDepth + 1;
ResultConverters = configurationExpression.Advanced.QueryableResultConverters.ToArray();
Binders = configurationExpression.Advanced.QueryableBinders.ToArray();
RecursiveQueriesMaxDepth = configurationExpression.Advanced.RecursiveQueriesMaxDepth;

Configuration = new ProfileMap(configurationExpression);
Profiles = new[] { Configuration }.Concat(configurationExpression.Profiles.Select(p => new ProfileMap(p, configurationExpression))).ToArray();

configurationExpression.Features.Configure(this);

foreach (var beforeSealAction in configurationExpression.Advanced.BeforeSealActions)
beforeSealAction?.Invoke(this);
Seal();
}



在构造函数内部,实际上是在构建一个MapperConfigurationExpression表达式,并将当前方法生成的Action用于对象的映射。表达式创建完成后,会进入到AutoMapper的核心方法Seal。

Seal方法解析

Seal方法是AutoMapper配置过程中的一个重要环节。

  1. 获取字段映射对象:首先,Seal方法会获取源类型(source Type)和目标类型(destination Type)的字段映射对象。
  2. 注册实现IProfiles的方法:然后,它会找到所有实现了IProfiles接口的方法,并将它们注册(即添加映射关系)到系统中。
private void Seal()
{
var derivedMaps = new List<Tuple<TypePair, TypeMap>>();
var redirectedTypes = new List<Tuple<TypePair, TypePair>>();

//获取所有的需要映射的集合 进行注册
foreach (var profile in Profiles)
{
//单个进行注册,传入当前对象
profile.Register(this);
}

//IncludeAllDerivedTypes 子类型
foreach (var typeMap in _configuredMaps.Values.Where(tm => tm.IncludeAllDerivedTypes))
{
//循环遍历获取可以赋值的派生类型
foreach (var derivedMap in _configuredMaps
.Where(tm =>
typeMap.SourceType.IsAssignableFrom(tm.Key.SourceType) &&
typeMap.DestinationType.IsAssignableFrom(tm.Key.DestinationType) &&
typeMap != tm.Value)
.Select(tm => tm.Value))
{
//获取派生类型
typeMap.IncludeDerivedTypes(derivedMap.SourceType, derivedMap.DestinationType);
}
}

foreach (var profile in Profiles)
{
profile.Configure(this);
}

foreach (var typeMap in _configuredMaps.Values)
{
_resolvedMaps[typeMap.Types] = typeMap;

if (typeMap.DestinationTypeOverride != null)
{
redirectedTypes.Add(Tuple.Create(typeMap.Types, new TypePair(typeMap.SourceType, typeMap.DestinationTypeOverride)));
}
derivedMaps.AddRange(GetDerivedTypeMaps(typeMap).Select(derivedMap => Tuple.Create(new TypePair(derivedMap.SourceType, typeMap.DestinationType), derivedMap)));
}
foreach (var redirectedType in redirectedTypes)
{
var derivedMap = FindTypeMapFor(redirectedType.Item2);
if (derivedMap != null)
{
_resolvedMaps[redirectedType.Item1] = derivedMap;
}
}
foreach (var derivedMap in derivedMaps.Where(derivedMap => !_resolvedMaps.ContainsKey(derivedMap.Item1)))
{
_resolvedMaps[derivedMap.Item1] = derivedMap.Item2;
}

foreach (var typeMap in _configuredMaps.Values)
{
typeMap.Seal(this);
}

Features.Seal(this);
}


注册过程

注册过程是将需要转化的实体和被映射的实体注册到TypeMap中,并最终添加到MapperConfigurationExpression表达式中。注册完成后,还会获取所有的派生类型并进行注册。


private void BuildTypeMap(IConfigurationProvider configurationProvider, ITypeMapConfiguration config)
{
//创建类型映射对象
//config.SourceType 需要转化的实体
//config.DestinationType 被映射的实体
// config.IsReverseMap 是否需要反向映射实体
var typeMap = TypeMapFactory.CreateTypeMap(config.SourceType, config.DestinationType, this, config.IsReverseMap);

config.Configure(typeMap);

configurationProvider.RegisterTypeMap(typeMap);
}

MapperConfigurationExpression表达式解析

当所有的类都已经完成关系映射后,会进入profile.Configure(this)方法。这个方法用于解析MapperConfigurationExpression表达式并进行映射。在此之后,会进行一些配置映射操作。


foreach (var typeMap in _configuredMaps.Values)
{
typeMap.Seal(this);
}

public void Seal(IConfigurationProvider configurationProvider)
{
if(_sealed)
{
return;
}
_sealed = true;

_inheritedTypeMaps.ForAll(tm => _includedMembersTypeMaps.UnionWith(tm._includedMembersTypeMaps));
foreach (var includedMemberTypeMap in _includedMembersTypeMaps)
{
includedMemberTypeMap.TypeMap.Seal(configurationProvider);
ApplyIncludedMemberTypeMap(includedMemberTypeMap);
}
_inheritedTypeMaps.ForAll(tm => ApplyInheritedTypeMap(tm));

_orderedPropertyMaps = PropertyMaps.OrderBy(map => map.MappingOrder).ToArray();
_propertyMaps.Clear();

MapExpression = CreateMapperLambda(configurationProvider, null);

Features.Seal(configurationProvider);
}



在TypeMap.Seal方法中,会调用CreateDestinationFunc方法创建一个lambda表达式,用于创建一个新的目标对象。CreateAssignmentFunc方法则用于为派生类生成赋值的lambda表达式,其中包含了在注册时使用的规则。

在映射过程中,如果两个对象的字段没有对应上的属性,CreateMapperFunc会产生一些默认规则,如默认值赋值等。这些生成的规则会存储在MapExpression表达式中。

总结

在使用AutoMapper的过程中,系统只会运行一次Seal方法,存储好对象之间的关系。在最终调用时,AutoMapper只会在已经存储好的对象关系中去寻找映射关系,并达成映射。

需要注意的是,如果在使用过程中不希望某些字段进行映射,可以使用IgnoreMapAttribute标记。在配置规则的过程中,如果发现有标记了IgnoreMapAttribute的字段,AutoMapper会自动忽略它们。

相关推荐

其实TensorFlow真的很水无非就这30篇熬夜练

好的!以下是TensorFlow需要掌握的核心内容,用列表形式呈现,简洁清晰(含表情符号,<300字):1.基础概念与环境TensorFlow架构(计算图、会话->EagerE...

交叉验证和超参数调整:如何优化你的机器学习模型

准确预测Fitbit的睡眠得分在本文的前两部分中,我获取了Fitbit的睡眠数据并对其进行预处理,将这些数据分为训练集、验证集和测试集,除此之外,我还训练了三种不同的机器学习模型并比较了它们的性能。在...

机器学习交叉验证全指南:原理、类型与实战技巧

机器学习模型常常需要大量数据,但它们如何与实时新数据协同工作也同样关键。交叉验证是一种通过将数据集分成若干部分、在部分数据上训练模型、在其余数据上测试模型的方法,用来检验模型的表现。这有助于发现过拟合...

深度学习中的类别激活热图可视化

作者:ValentinaAlto编译:ronghuaiyang导读使用Keras实现图像分类中的激活热图的可视化,帮助更有针对性...

超强,必会的机器学习评估指标

大侠幸会,在下全网同名[算法金]0基础转AI上岸,多个算法赛Top[日更万日,让更多人享受智能乐趣]构建机器学习模型的关键步骤是检查其性能,这是通过使用验证指标来完成的。选择正确的验证指...

机器学习入门教程-第六课:监督学习与非监督学习

1.回顾与引入上节课我们谈到了机器学习的一些实战技巧,比如如何处理数据、选择模型以及调整参数。今天,我们将更深入地探讨机器学习的两大类:监督学习和非监督学习。2.监督学习监督学习就像是有老师的教学...

Python教程(三十八):机器学习基础

...

Python 模型部署不用愁!容器化实战,5 分钟搞定环境配置

你是不是也遇到过这种糟心事:花了好几天训练出的Python模型,在自己电脑上跑得顺顺当当,一放到服务器就各种报错。要么是Python版本不对,要么是依赖库冲突,折腾半天还是用不了。别再喊“我...

超全面讲透一个算法模型,高斯核!!

...

神经网络与传统统计方法的简单对比

传统的统计方法如...

AI 基础知识从0.1到0.2——用“房价预测”入门机器学习全流程

...

自回归滞后模型进行多变量时间序列预测

下图显示了关于不同类型葡萄酒销量的月度多元时间序列。每种葡萄酒类型都是时间序列中的一个变量。假设要预测其中一个变量。比如,sparklingwine。如何建立一个模型来进行预测呢?一种常见的方...

苹果AI策略:慢哲学——科技行业的“长期主义”试金石

苹果AI策略的深度原创分析,结合技术伦理、商业逻辑与行业博弈,揭示其“慢哲学”背后的战略智慧:一、反常之举:AI狂潮中的“逆行者”当科技巨头深陷AI军备竞赛,苹果的克制显得格格不入:功能延期:App...

时间序列预测全攻略,6大模型代码实操

如果你对数据分析感兴趣,希望学习更多的方法论,希望听听经验分享,欢迎移步宝藏公众号...

AI 基础知识从 0.4 到 0.5—— 计算机视觉之光 CNN

...

取消回复欢迎 发表评论: