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 无法解析

AutoMapper

C# 引用AutoMapper提示Mapper类不具有CreateMap方法,怎么解决?

AutoMapper.Mapper.CreateMap报“System.NullReferenceException: 未将对象引用设置到对象的实例。”异常复现

AutoMapper新语法

忽略使用 Automapper 映射一个属性