AutoMapper/AutoMapper — Issue #142: CreateMap<IDataReader, TDest>().ConstructUsing(...) doesn't use specified factory
Author: kalebpederson
Created: 2011-11-03 19:07:10+00:00
State: open

When mapping an IDataReader or IDataRecord the DataReaderMapper is used internally by AutoMapper, but it fails to create the destination type using the specified factory.

Here's a test case (using Moq to mock the IDataRecord):

public class MyClass
{
public int Value { get; private set; }
public MyClass(int value) { Value = value; }
}

[TestFixture]
public class DataReaderObjectMapperTest
{
[Test]
public void Method_provided_to_ConstructUsing_is_used_to_create_object_when_mapping_with_IDataRecord()
{
const int VALUE = 42;
var dataRecord = Mock.Of(
x => x.FieldCount == 1 && x.IsDBNull(0) == false
&& x.GetName(0) == "Value" && x.GetFieldType(0) == typeof(int)
&& x[0] == (object)VALUE
);
Mapper.CreateMap().ConstructUsing(src => new MyClass((int)src[0]));
var mapped = Mapper.Map(dataRecord);
Assert.AreEqual(VALUE, mapped.Value);
}
}

The result is the following stack trace:

AutoMapper.AutoMapperMappingException : Trying to map System.Data.IDataRecord to ConstructUsing.MyClass.
Using mapping configuration for System.Data.IDataRecord to ConstructUsing.MyClass
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
----> System.ArgumentNullException : Value cannot be null.
Parameter name: con
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) in MappingEngine.cs: line 314
at AutoMapper.MappingEngine.Map(Object source, Type sourceType, Type destinationType, Action`1 opts) in MappingEngine.cs: line 98
at AutoMapper.MappingEngine.Map(Object source, Action`1 opts) in MappingEngine.cs: line 49
at AutoMapper.MappingEngine.Map(Object source) in MappingEngine.cs: line 38
at AutoMapper.Mapper.Map(Object source) in C:\Source\External\AutoMapper\src\AutoMapper\Mapper.cs: line 27
at ConstructUsing.DataReaderObjectMapperTest.Method_provided_to_ConstructUsing_is_used_to_create_object_when_mapping_with_IDataRecord() in DataReaderObjectMapperTest.cs: line 27
--ArgumentNullException
at System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, ConstructorInfo con)
at AutoMapper.Mappers.DataReaderMapper.CreateBuilder(Type destinationType, IDataRecord dataRecord) in DataReaderMapper.cs: line 73
at AutoMapper.Mappers.DataReaderMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) in DataReaderMapper.cs: line 40
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) in MappingEngine.cs: line 308

I'm not yet familiar enough with the code to know how to get access to the provided constructor function.