2010-06-17 3 views
5

псевдопользователей код конфигурации отображения (как показано ниже) не представляется возможным, так как лямбда только позволяет нам доступа типа IDataReader, Тогда как когда на самом деле отображение, AutoMapper достигнет в каждой «ячейки» каждого IDataRecord в то время как IDataReader.Read() == true:Могу ли я настроить AutoMapper для чтения из пользовательских имен столбцов при сопоставлении с IDataReader?

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

Может ли кто-нибудь подумать о том, как это сделать, используя конфигурацию AutoMapper во время выполнения или просто какой-то другой динамический подход, соответствующий требованиям ниже.

Требование должно поддерживать все входящие IDataReader которые могут иметь имена столбцов, которые не соответствуют именам свойств MyDTO, и нет соглашения об именах, на которые я могу положиться. Вместо этого мы попросим пользователя во время выполнения перекрестно ссылаться на ожидаемые имена столбцов с фактическими именами столбцов, найденными в IDataReader, с помощью IDataReader.GetSchemaTable().

ответ

3

Я не знаю, о automapper но я отображение DataReader для объектов, использующих 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 в любого типа объекта


ОК, так что согласно вашему требованию uirements, я предполагаю, что это должно быть так:

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

+1 для очень интересного ответа. Однако он еще не удовлетворяет требованиям, поскольку он все еще ожидает, что имя столбца будет соответствовать имени свойства. Спасибо за хедз-ап по ValueInjecter в любом случае. – rohancragg

+2

@rohancragg у вас есть все имена свойств из объекта (targetProps), и вы можете получить все имена из datareader (source.GetName (theName)), так что вы можете изменить его в соответствии с вашими потребностями – Omu

+1

@rohancragg Я отредактировал мой вопрос, я думаю, что этот способ должен работать (я не пробовал, но надеюсь) – Omu

Смежные вопросы