diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index db1cbc32851e2bd3432bcbd271b58a866de37c90..1883c866ed2404f8c34a7cf5db305c1461ae44fc 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -670,7 +670,7 @@ private static object GetStructDeserializer(IDataReader reader) }) .Where(info => info.Setter != null) .ToList(); - + var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (length == -1) { length = reader.FieldCount - startBound; @@ -684,9 +684,11 @@ private static object GetStructDeserializer(IDataReader reader) var setters = ( from n in names - let prop = properties.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCulture)) // case sensitive first - ?? properties.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCultureIgnoreCase)) // case insensitive second - select new { Name = n, Info = prop } + let prop = properties.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCulture)) // property case sensitive first + ?? properties.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCultureIgnoreCase)) // property case insensitive second + let field = prop != null ? null : (fields.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCulture)) // field case sensitive third + ?? fields.FirstOrDefault(p => string.Equals(p.Name, n, StringComparison.InvariantCultureIgnoreCase))) // field case insensitive fourth + select new { Name = n, Property = prop, Field = field } ).ToList(); @@ -703,7 +705,7 @@ private static object GetStructDeserializer(IDataReader reader) var @allDone = il.DefineLabel(); foreach (var item in setters) { - if (item.Info != null) + if (item.Property != null || item.Field != null) { il.Emit(OpCodes.Dup); // stack is now [target][target] Label isDbNullLabel = il.DefineLabel(); @@ -720,15 +722,22 @@ private static object GetStructDeserializer(IDataReader reader) il.Emit(OpCodes.Brtrue_S, isDbNullLabel); // stack is now [target][target][value-as-object] // unbox nullable enums as the primitive, i.e. byte etc - var nullUnderlyingType = Nullable.GetUnderlyingType(item.Info.Type); - var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : item.Info.Type; + Type memberType = item.Property != null ? item.Property.Type : item.Field.FieldType; + var nullUnderlyingType = Nullable.GetUnderlyingType(memberType); + var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : memberType; il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value] if (nullUnderlyingType != null && nullUnderlyingType.IsEnum) { - il.Emit(OpCodes.Newobj, item.Info.Type.GetConstructor(new[] { nullUnderlyingType })); + il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType })); + } + if (item.Property != null) + { + il.Emit(OpCodes.Callvirt, item.Property.Setter); // stack is now [target] + } + else + { + il.Emit(OpCodes.Stfld, item.Field); // stack is now [target] } - - il.Emit(OpCodes.Callvirt, item.Info.Setter); // stack is now [target] il.Emit(OpCodes.Br_S, finishLabel); // stack is now [target] il.MarkLabel(isDbNullLabel); // incoming stack: [target][target][value] diff --git a/Tests/Tests.cs b/Tests/Tests.cs index f9803fe042c8de6d544af212c2ffc682a53c4409..1a3d3a263f40d6379cb4cb5514cc89b2721e5bf8 100644 --- a/Tests/Tests.cs +++ b/Tests/Tests.cs @@ -322,6 +322,36 @@ public void TestMultiMapDynamic() connection.Execute("drop table #Users drop table #Posts"); } + public void TestFieldsAndPrivates() + { + var data = connection.Query( + @"select a=1,b=2,c=3,d=4,f='5'").Single(); + + + data.a.IsEqualTo(1); + data.GetB().IsEqualTo(2); + data.c.IsEqualTo(3); + data.GetD().IsEqualTo(4); + data.e.IsEqualTo(5); + + + } + + private class TestFieldCaseAndPrivatesEntity + { + public int a { get; set; } + private int b { get; set; } + public int GetB() { return b; } + public int c = 0; + private int d = 0; + public int GetD() { return d; } + public int e { get; set; } + private string f + { + get { return e.ToString(); } + set { e = int.Parse(value); } + } + } public void TestMultiReaderBasic() {