从IDataReader映射时,是否可以将AutoMapper配置为从自定义列名读取?

时间:2010-06-17 11:52:20

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

用于映射配置的Psuedo代码(如下所示)是不可能的,因为lambda只允许我们访问Type IDataReader,在实际映射时,AutoMapper将到达每个IDataRecord的每个“单元格”而{{1} }:

IDataReader.Read() == true

任何人都可以想到在运行时使用AutoMapper配置或者只是满足下面要求的其他动态方法的方法。

要求是支持任何传入的var mappingConfig = Mapper.CreateMap<IDataReader, IEnumerable<MyDTO>>(); mappingConfig.ForMember( destination => destination.???, options => options.MapFrom(source => source.???)); ,它们的列名可能与IDataReader的属性名称不匹配,并且没有我可以依赖的命名约定。相反,我们会要求用户在运行时使用MyDTOIDataReader通过IDataReader.GetSchemaTable()交叉引用预期的列名称。

1 个答案:

答案 0 :(得分:3)

我不知道自动播放器,但是我正在使用ValueInjecter将datareader映射到对象:

 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(
...