【问题标题】:AutoMapper: read Mapper Configuration at runtime?AutoMapper:在运行时读取 Mapper 配置?
【发布时间】: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 配置中。

【问题讨论】:

    标签: excel automapper datareader


    【解决方案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 文件中的列名可以随时更改。
    • 我不知道,但你现在拥有的肯定是......不好:)
    • 设计过度了。它需要一个简单的问题并以复杂的方式解决它。虽然我明白你的意思,但最终结果......我不太愿意研究这个,但即使为列名或索引命名常量似乎更好。
    • 您对过度工程的看法可能是正确的。我做了太多工作来避免命名常量/双重映射。回到绘图板。
    猜你喜欢
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多