Код Psuedo для отображения конфигурации (как ниже) не возможен, так как лямбда только позволяет нам тип доступа 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
через IDataReader.GetSchemaTable()
.
Я не знаю об автоматическом преобразователе, но я сопоставляю устройство чтения данных с объектами с помощью ValueInjecter следующим образом:
while (dr.Read())
{
var o = new User();
o.InjectFrom<DataReaderInjection>(dr);
return o;
}
и DataReaderInjection (что-то вроде ValueResolver для Automapper)
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(
...