【问题标题】:Can I configure AutoMapper to read from custom column names when mapping from IDataReader?从 IDataReader 映射时,我可以将 AutoMapper 配置为从自定义列名中读取吗?
【发布时间】:2011-03-04 22:23:10
【问题描述】:

映射配置的伪代码(如下)是不可能的,因为 lambda 只允许我们访问 Type IDataReader,而在实际映射时,AutoMapper 将到达每个 IDataRecord 的每个“单元格”,而 IDataReader.Read() == true

var mappingConfig = Mapper.CreateMap<IDataReader, IEnumerable<MyDTO>>();
mappingConfig.ForMember(
    destination => destination.???,
    options => options.MapFrom(source => source.???));

谁能想到在运行时使用 AutoMapper 配置或仅满足以下要求的其他动态方法来做到这一点。

要求是支持任何传入的IDataReader,其列名可能与MyDTO 的属性名称不匹配,并且没有我可以依赖的命名约定。相反,我们会在运行时要求用户通过IDataReader.GetSchemaTable() 将预期的列名与在IDataReader 中找到的实际列名交叉引用。

【问题讨论】:

    标签: c# .net automapper system.data valueinjecter


    【解决方案1】:

    我不了解自动映射器,但我正在使用 ValueInjecter 将数据读取器映射到对象,如下所示:

     while (dr.Read())
     {
        var o = new User();
        o.InjectFrom<DataReaderInjection>(dr);
        return o;
     }
    

    和 DataReaderInjection(类似于 Automapper 的 ValueResolver)

    public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
        {
            protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
            {
                for (var i = 0; i < source.FieldCount; i++)
                {
                    var activeTarget = targetProps.GetByName(source.GetName(i), true);
                    if (activeTarget == null) continue;
    
                    var value = source.GetValue(i);
                    if (value == DBNull.Value) continue;
    
                    activeTarget.SetValue(target, value);
                }
            }
        }
    

    您可以使用它来将值从 IDataReader 注入到任何类型的对象


    好的,所以根据你的要求,我想应该是这样的:
    public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
            {
                protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
                {
                    var columns = source.GetSchemaTable().Columns;
                    for (var i = 0; i < columns.Count; i++)
                    {
                        var c = columns[i];
    
                        var targetPropName = c.ColumnName; //default is the same as columnName
    
                        if (c.ColumnName == "Foo") targetPropName = "TheTargetPropForFoo";
                        if (c.ColumnName == "Bar") targetPropName = "TheTargetPropForBar";
                        //you could also create a dictionary and use it here
    
                        var targetProp = targetProps.GetByName(targetPropName);
                        //go to next column if there is no such property in the target object
                        if (targetProp == null) continue;
    
                        targetProp.SetValue(target, columns[c.ColumnName]);
                    }
                }
            }
    

    我在这里使用了 GetSchemaTable,就像你想要的那样:)


    好的,如果您想将一些东西传递给注入,您可以通过多种方式进行,方法如下:
    o.InjectFrom(new DataReaderInjection(stuff), dr);
    //you need a constructor with parameters for the DataReaderInjection in this case
    
    var ri = new DataReaderInjection();
    ri.Stuff = stuff;
    o.InjectFrom(ri, dr);
    //you need to add a property in this case
    

    这里有个提示(给带参数的构造方法)

      public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
         {
            private IDictionary<string, string> stuff;
            public DataReaderInjection(IDictionary<string,string> stuff)
            {
              this.stuff = stuff;
            }
                        protected override void Inject(
    ...
    

    【讨论】:

    • +1 以获得非常有趣的答案。但是,它(尚未)满足要求,因为它仍然希望“列”名称与属性名称匹配。无论如何,感谢您对 ValueInjecter 的提醒。
    • @rohancragg 您拥有对象 (targetProps) 中的所有属性名称,并且您可以从数据读取器 (source.GetName(theName)) 中获取所有名称,因此您可以对其进行修改以满足您的需求
    • @rohancragg 我已经编辑了我的问题,我认为这种方式应该可行(我没有尝试过,但我希望如此)
    • 太好了,谢谢。但是,我认为需要最后一步......如何将字典作为参数传递给 DataReaderInjection.Inject()?
    • @rohancragg 我再次编辑了这个问题;),基本上你只需在注入中添加一个带参数的构造函数,以稍微不同的方式调用它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多