AutoMapper:在运行时读取 Mapper 配置?
Posted
技术标签:
【中文标题】AutoMapper:在运行时读取 Mapper 配置?【英文标题】:AutoMapper: read Mapper Configuration at runtime? 【发布时间】:2018-04-02 01:26:21 【问题描述】:如果我的 AutoMapper 术语有任何错误,请原谅我,我是图书馆的新手。
我的代码
我创建了这个Map
是为了从IDataReader
映射到PersonDto
。代码效果很好,我可以从IDataReader
生成PersonDto
对象。没有问题。
var map = CreateMap<IDataReader, PersonDto>()
.ForMember(o => o.FirstName, opt => opt.MapFrom(row => row["First Name"]))
.ForMember(o => o.LastName, opt => opt.MapFrom(row => row["Last Name"]))
.ForMember(o => o.Birthday, opt => opt.MapFrom(row => row["Date of Birth"]))
我的问题
我正在寻找某种方法来获取上面定义的map
,并取回字符串“First Name”, “Last Name”, “Date of Birth”
。
我为什么要这样做(我的目标是什么)
本节是为了以防万一有人对我为什么要执行上述操作而摸不着头脑。正如我所提到的,我是图书馆的新手,所以我不知道我所要求的是否是计数器 Automapper 的预期用途。
我正在使用 ExcelDataReader 库从 Excel 电子表格中读取数据。 xlsx 来自第 3 方供应商,每隔几个月他们就会更改 xlsx 的布局(重新排序/重命名标题)。他们不提供 Web API 或其他方式来获取数据。
此外,标题行的位置是不可预测的。供应商在同一工作表的数据上方插入图表。为了解决这个问题,我写了一个给定标题名称的函数,将返回标题行的索引:
string headerNames[] = “First Name”, “Last Name” ...
int headerIndex = findHeaderRow(dataReader, headerNames)
我希望能够从 AutoMapper 配置中获取标头名称,以便我可以将它们直接提供给 findHeaderRow
,而无需显式定义字符串数组。
我可以像这样创建我的地图,但我觉得它很脆弱。
var map = CreateMap<IDataReader, PersonDto>()
.ForMember(o => o.FirstName, opt => opt.MapFrom(row => row[headerNames[0]]))
.ForMember(o => o.LastName, opt => opt.MapFrom(row => row[headerNames[1]]))
结论
最终,我希望这个 Excel 导入代码在发生这些不可避免的布局更改时能够简单地更新。我希望只在一个地方定义标题名称,而我看到的最佳位置是在 AutoMapper 配置中。
【问题讨论】:
【参考方案1】:这就是我想出的。它有效,我只是不知道它有多强大,或者是否有更好的方法来做到这一点。
public static string[] GetSourceColumnNames<TSource, TDestination>(MapperConfiguration config)
var maps = config.ResolveTypeMap(typeof(TSource), typeof(TDestination)).GetPropertyMaps();
string[] columnNames = new string[maps.Length];
for (int i = 0; i < maps.Length; i++)
var body = maps[i].CustomExpression.Body;
if (body is IArgumentProvider)
var provider = (IArgumentProvider)body;
if (provider.ArgumentCount > 0)
columnNames[i] = provider.GetArgument(0).ToString().Trim('"');
return columnNames;
【讨论】:
我认为您应该从数据读取器中获取这些字符串,而不是从 AM 中获取。 字符串未在DataReader
中定义。 Excel 文件中的列名可以随时更改。
我不知道,但你现在拥有的肯定是......不好:)
设计过度了。它需要一个简单的问题并以复杂的方式解决它。虽然我明白你的意思,但最终结果......我不太愿意研究这个,但即使为列名或索引命名常量似乎更好。
您对过度工程的看法可能是正确的。我做了太多工作来避免命名常量/双重映射。回到绘图板。以上是关于AutoMapper:在运行时读取 Mapper 配置?的主要内容,如果未能解决你的问题,请参考以下文章
Automapper.Mapper.CreateMap 无法解析
C# 引用AutoMapper提示Mapper类不具有CreateMap方法,怎么解决?
AutoMapper.Mapper.CreateMap报“System.NullReferenceException: 未将对象引用设置到对象的实例。”异常复现