5

マッピング構成の疑似コード (以下のように) は不可能です。これは、ラムダがタイプ IDataReader にしかアクセスできないためです。一方、実際にマッピングすると、AutoMapper は各IDataRecordwhileの各「セル」に到達しIDataReader.Read() == trueます。

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

実行時に AutoMapper 構成を使用するか、以下の要件を満たす他の動的なアプローチを使用して、これを行う方法を誰でも思いつくことができますか?

要件はIDataReader、のプロパティ名と一致しない列名を持つ可能性のある受信をサポートすることでMyDTOあり、信頼できる命名規則はありません。IDataReader代わりに、実行時にユーザーに期待される列名をviaで見つかった実際の列名と相互参照するように求めますIDataReader.GetSchemaTable()

4

1 に答える 1

3

automapper についてはわかりませんが、次のように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(
...
于 2010-06-17T12:07:04.607 に答える