Commit bebe80bc authored by Marc Gravell's avatar Marc Gravell

Support get-only C# 6 properties, i.e. `public int Id {get;}`

parent b9288b4a
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup> </ItemGroup>
......
...@@ -3696,5 +3696,17 @@ protected static SqliteConnection GetSqliteConnection(bool open = true) ...@@ -3696,5 +3696,17 @@ protected static SqliteConnection GetSqliteConnection(bool open = true)
return connection; return connection;
} }
#endif #endif
} [Fact]
public void GetOnlyProperties()
{
var obj = connection.QuerySingle<HazGetOnly>("select 42 as [Id], 'def' as [Name];");
obj.Id.IsEqualTo(42);
obj.Name.IsEqualTo("def");
}
class HazGetOnly
{
public int Id { get; }
public string Name { get; } = "abc";
}
}
} }
...@@ -164,13 +164,25 @@ public SqlMapper.IMemberMap GetMember(string columnName) ...@@ -164,13 +164,25 @@ public SqlMapper.IMemberMap GetMember(string columnName)
if (property != null) if (property != null)
return new SimpleMemberMap(columnName, property); return new SimpleMemberMap(columnName, property);
// roslyn automatically implemented properties, in particular for get-only properties: <{Name}>k__BackingField;
var backingFieldName = $"<{columnName}>k__BackingField";
// preference order is:
// exact match over underscre match, backing fields over regular fields, exact case over wrong case
var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)); ?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
if (field == null && MatchNamesWithUnderscores) if (field == null && MatchNamesWithUnderscores)
{ {
field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.Ordinal)) var effectiveColumnName = columnName.Replace("_", "");
?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.OrdinalIgnoreCase)); backingFieldName = $"<{effectiveColumnName}>k__BackingField";
field = _fields.FirstOrDefault(p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
?? _fields.FirstOrDefault(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
} }
if (field != null) if (field != null)
......
...@@ -2798,7 +2798,7 @@ static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, LocalBuild ...@@ -2798,7 +2798,7 @@ static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, LocalBuild
) )
{ {
var returnType = type.IsValueType() ? typeof(object) : type; var returnType = type.IsValueType() ? typeof(object) : type;
var dm = new DynamicMethod($"Deserialize{Guid.NewGuid()}", returnType, new[] { typeof(IDataReader) }, true); var dm = new DynamicMethod($"Deserialize{Guid.NewGuid()}", returnType, new[] { typeof(IDataReader) }, type, true);
var il = dm.GetILGenerator(); var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int)); il.DeclareLocal(typeof(int));
il.DeclareLocal(type); il.DeclareLocal(type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment