diff --git a/src/DbReader.Tests/InstanceReaderTests.cs b/src/DbReader.Tests/InstanceReaderTests.cs index 50d4506..58bbb2d 100644 --- a/src/DbReader.Tests/InstanceReaderTests.cs +++ b/src/DbReader.Tests/InstanceReaderTests.cs @@ -410,6 +410,17 @@ public void ShouldUseDefaultValue() instance.Property.Value.ShouldBe(42); } + [Fact] + public void ShouldNotUseDefaultValue() + { + var dataRecord = new { Id = 1, Property = 42 }.ToDataRecord(); + DbReaderOptions.WhenReading().Use((dr, i) => new CustomValueType(dr.GetInt32(i))).WithDefaultValue(new CustomValueType(82)); + var reader = GetReader>(); + var instance = reader.Read(dataRecord, string.Empty); + instance.Property.Value.ShouldBe(42); + } + + public class CustomValueType { diff --git a/src/DbReader/Construction/ConstructorReaderMethodBuilder.cs b/src/DbReader/Construction/ConstructorReaderMethodBuilder.cs index e1409c8..72431ee 100644 --- a/src/DbReader/Construction/ConstructorReaderMethodBuilder.cs +++ b/src/DbReader/Construction/ConstructorReaderMethodBuilder.cs @@ -10,7 +10,7 @@ /// an instance of using constructor arguments. /// /// The type of object to be created. - public class ConstructorReaderMethodBuilder : ReaderMethodBuilder + public class ConstructorReaderMethodBuilder : ReaderMethodBuilder { private readonly IConstructorSelector constructorSelector; @@ -50,7 +50,7 @@ private void LoadConstructorArguments(ILGenerator il, ConstructorInfo constructo for (int parameterIndex = 0; parameterIndex < parameters.Length; parameterIndex++) { EmitCheckForValidOrdinal(il, parameterIndex, tryLoadNullValue); - EmitCheckForDbNull(il, parameterIndex, tryLoadNullValue); + EmitGoLabelIfDbNull(il, parameterIndex, tryLoadNullValue); } for (int i = 0; i < parameters.Length; i++) diff --git a/src/DbReader/Construction/PropertyReaderMethodBuilder.cs b/src/DbReader/Construction/PropertyReaderMethodBuilder.cs index 609e72a..f0c4404 100644 --- a/src/DbReader/Construction/PropertyReaderMethodBuilder.cs +++ b/src/DbReader/Construction/PropertyReaderMethodBuilder.cs @@ -133,13 +133,16 @@ private void EmitPropertySetters(ILGenerator generator, LocalBuilder instanceVar private void EmitPropertySetter(ILGenerator il, PropertyInfo property, int propertyIndex, LocalBuilder instanceVariable) { MethodInfo getMethod = MethodSelector.Execute(property.PropertyType); + var checkForDefaultValueLabel = il.DefineLabel(); var endLabel = il.DefineLabel(); - EmitCheckForValidOrdinal(il, propertyIndex, endLabel); - EmitCheckForDbNull(il, propertyIndex, endLabel); + EmitCheckForValidOrdinal(il, propertyIndex, checkForDefaultValueLabel); + EmitGoLabelIfDbNull(il, propertyIndex, checkForDefaultValueLabel); LoadInstance(il, instanceVariable); EmitGetValue(il, propertyIndex, getMethod, property.PropertyType); EmitCallPropertySetterMethod(il, property); - il.MarkLabel(endLabel); + il.MarkLabel(checkForDefaultValueLabel); + EmitCheckForValidOrdinal(il, propertyIndex, endLabel); + EmitGoLabelIfNotDbNull(il, propertyIndex, endLabel); if (ValueConverter.HasDefaultValue(property.PropertyType)) { var openGenericGetDefaultValueMethod = typeof(ValueConverter).GetMethod(nameof(ValueConverter.GetDefaultValue), BindingFlags.Static | BindingFlags.NonPublic); @@ -148,6 +151,7 @@ private void EmitPropertySetter(ILGenerator il, PropertyInfo property, int prope il.Emit(OpCodes.Call, getDefaultValueMethod); EmitCallPropertySetterMethod(il, property); } + il.MarkLabel(endLabel); } } } \ No newline at end of file diff --git a/src/DbReader/Construction/ReaderMethodBuilder.cs b/src/DbReader/Construction/ReaderMethodBuilder.cs index b3d45b6..6eedc27 100644 --- a/src/DbReader/Construction/ReaderMethodBuilder.cs +++ b/src/DbReader/Construction/ReaderMethodBuilder.cs @@ -66,7 +66,7 @@ protected void EmitCheckForValidOrdinal(ILGenerator il, int index, Label trueLab LoadOrdinal(il, index); LoadIntegerValueOfMinusOne(il); EmitCompareValues(il); - EmitGotoEndLabelIfValueIsTrue(il, trueLabel); + EmitGotoLabelIfValueIsTrue(il, trueLabel); } /// @@ -76,12 +76,20 @@ protected void EmitCheckForValidOrdinal(ILGenerator il, int index, Label trueLab /// The index of the ordinal to check. /// The that represents where to jump if /// the value about to be read from the is . - protected void EmitCheckForDbNull(ILGenerator il, int index, Label trueLabel) + protected void EmitGoLabelIfDbNull(ILGenerator il, int index, Label trueLabel) { LoadDataRecord(il); LoadOrdinal(il, index); EmitCallIsDbNullMethod(il); - EmitGotoEndLabelIfValueIsTrue(il, trueLabel); + EmitGotoLabelIfValueIsTrue(il, trueLabel); + } + + protected void EmitGoLabelIfNotDbNull(ILGenerator il, int index, Label falseLabel) + { + LoadDataRecord(il); + LoadOrdinal(il, index); + EmitCallIsDbNullMethod(il); + EmitGotoLabelIfValueIsFalse(il, falseLabel); } /// @@ -168,9 +176,14 @@ private static void EmitCompareValues(ILGenerator il) il.Emit(OpCodes.Ceq); } - private static void EmitGotoEndLabelIfValueIsTrue(ILGenerator il, Label endLabel) + private static void EmitGotoLabelIfValueIsTrue(ILGenerator il, Label trueLabel) + { + il.Emit(OpCodes.Brtrue, trueLabel); + } + + private static void EmitGotoLabelIfValueIsFalse(ILGenerator il, Label trueLabel) { - il.Emit(OpCodes.Brtrue, endLabel); + il.Emit(OpCodes.Brfalse, trueLabel); } private static Func CreateDelegate(IMethodSkeleton methodSkeleton)