Skip to content

Commit bebe80b

Browse files
committed
Support get-only C# 6 properties, i.e. public int Id {get;}
1 parent b9288b4 commit bebe80b

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

Dapper.Tests/Dapper.Tests.xproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
<PropertyGroup>
1515
<SchemaVersion>2.0</SchemaVersion>
1616
</PropertyGroup>
17-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" />
17+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
18+
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
19+
</PropertyGroup>
1820
<ItemGroup>
1921
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
2022
</ItemGroup>

Dapper.Tests/Tests.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3696,5 +3696,17 @@ protected static SqliteConnection GetSqliteConnection(bool open = true)
36963696
return connection;
36973697
}
36983698
#endif
3699-
}
3699+
[Fact]
3700+
public void GetOnlyProperties()
3701+
{
3702+
var obj = connection.QuerySingle<HazGetOnly>("select 42 as [Id], 'def' as [Name];");
3703+
obj.Id.IsEqualTo(42);
3704+
obj.Name.IsEqualTo("def");
3705+
}
3706+
class HazGetOnly
3707+
{
3708+
public int Id { get; }
3709+
public string Name { get; } = "abc";
3710+
}
3711+
}
37003712
}

Dapper/DefaultTypeMap.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,25 @@ public SqlMapper.IMemberMap GetMember(string columnName)
164164
if (property != null)
165165
return new SimpleMemberMap(columnName, property);
166166

167+
// roslyn automatically implemented properties, in particular for get-only properties: <{Name}>k__BackingField;
168+
var backingFieldName = $"<{columnName}>k__BackingField";
169+
170+
// preference order is:
171+
// exact match over underscre match, backing fields over regular fields, exact case over wrong case
167172
var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
168-
?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));
173+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase))
174+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
175+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
169176

170177
if (field == null && MatchNamesWithUnderscores)
171178
{
172-
field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.Ordinal))
173-
?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.OrdinalIgnoreCase));
179+
var effectiveColumnName = columnName.Replace("_", "");
180+
backingFieldName = $"<{effectiveColumnName}>k__BackingField";
181+
182+
field = _fields.FirstOrDefault(p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal))
183+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase))
184+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
185+
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
174186
}
175187

176188
if (field != null)

Dapper/SqlMapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2798,7 +2798,7 @@ private static Func<IDataReader, object> GetTypeDeserializerImpl(
27982798
)
27992799
{
28002800
var returnType = type.IsValueType() ? typeof(object) : type;
2801-
var dm = new DynamicMethod($"Deserialize{Guid.NewGuid()}", returnType, new[] { typeof(IDataReader) }, true);
2801+
var dm = new DynamicMethod($"Deserialize{Guid.NewGuid()}", returnType, new[] { typeof(IDataReader) }, type, true);
28022802
var il = dm.GetILGenerator();
28032803
il.DeclareLocal(typeof(int));
28042804
il.DeclareLocal(type);

0 commit comments

Comments
 (0)