Skip to content

Commit 3ea23d0

Browse files
committed
add support CustomDeserializer.
1 parent 049f171 commit 3ea23d0

13 files changed

+166
-44
lines changed

build/version.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<VersionMajor>4</VersionMajor>
44
<VersionMinor>0</VersionMinor>
5-
<VersionPatch>40</VersionPatch>
5+
<VersionPatch>41</VersionPatch>
66
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
77
</PropertyGroup>
88
</Project>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using System.Threading.Tasks;
5+
using SmartSql.Deserializer;
6+
using Xunit;
7+
8+
namespace SmartSql.Test.Unit.Deserializer
9+
{
10+
public class DeserializerFactoryTest
11+
{
12+
[Fact]
13+
public void Add()
14+
{
15+
var builder = new SmartSqlBuilder()
16+
.UseDataSource("SqlServer", "Data Source=.;Initial Catalog=SmartSqlTestDB;Integrated Security=True")
17+
.UseAlias("DeserializerFactoryTest")
18+
.AddDeserializer(new CustomDeserializer()).Build();
19+
var result = builder.SqlMapper.QuerySingle<CustomResultType>(new RequestContext
20+
{
21+
RealSql = "Select NewId()"
22+
});
23+
Assert.NotNull(result);
24+
}
25+
26+
27+
public class CustomResultType
28+
{
29+
public Guid Id { get; set; }
30+
}
31+
32+
public class CustomDeserializer : IDataReaderDeserializer
33+
{
34+
public bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false)
35+
{
36+
return resultType == typeof(CustomResultType);
37+
}
38+
public TResult ToSinge<TResult>(ExecutionContext executionContext)
39+
{
40+
var dataReader = executionContext.DataReaderWrapper;
41+
if (!dataReader.HasRows) return default(TResult);
42+
dataReader.Read();
43+
var id = dataReader.GetGuid(0);
44+
object result = new CustomResultType { Id = id };
45+
return (TResult)result;
46+
}
47+
48+
public IList<TResult> ToList<TResult>(ExecutionContext executionContext)
49+
{
50+
throw new NotImplementedException();
51+
}
52+
public Task<TResult> ToSingeAsync<TResult>(ExecutionContext executionContext)
53+
{
54+
55+
throw new NotImplementedException();
56+
}
57+
58+
public Task<IList<TResult>> ToListAsync<TResult>(ExecutionContext executionContext)
59+
{
60+
throw new NotImplementedException();
61+
}
62+
}
63+
}
64+
}

src/SmartSql.Test.Unit/Deserializer/DynamicDeserializerTest.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using SmartSql.Test.Entities;
22
using System;
3+
using System.Collections;
34
using System.Collections.Generic;
45
using System.Linq;
56
using System.Text;
@@ -9,7 +10,7 @@
910
namespace SmartSql.Test.Unit.Deserializer
1011
{
1112
[Collection("GlobalSmartSql")]
12-
public class DynamicDeserializerTest
13+
public class DynamicDeserializerTest
1314
{
1415
protected ISqlMapper SqlMapper { get; }
1516

@@ -39,10 +40,31 @@ public void Query_Dynamic()
3940
});
4041
Assert.NotEqual(0, result.FirstOrDefault().Id);
4142
}
43+
[Fact]
44+
public void Query_Dynamic_AsHashtable()
45+
{
46+
var result = SqlMapper.Query<dynamic>(new RequestContext
47+
{
48+
Scope = nameof(AllPrimitive),
49+
SqlId = "Query",
50+
Request = new { Taken = 10 }
51+
});
4252

53+
var hashtableList = result.Select(item =>
54+
{
55+
var dic = item as IDictionary<string, object>;
56+
var hashTable = new Hashtable(dic.Count);
57+
foreach (var kv in dic)
58+
{
59+
hashTable.Add(kv.Key, kv.Value);
60+
}
61+
return hashTable;
62+
});
63+
}
4364
[Fact]
4465
public async Task QuerySingleAsync_Dynamic()
4566
{
67+
4668
var result = await SqlMapper.QuerySingleAsync<dynamic>(new RequestContext
4769
{
4870
Scope = nameof(AllPrimitive),
@@ -63,4 +85,4 @@ public async Task QueryAsync_Dynamic()
6385
Assert.NotEqual(0, result.FirstOrDefault().Id);
6486
}
6587
}
66-
}
88+
}
Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,30 @@
11
using SmartSql.Reflection.TypeConstants;
22
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
35

46
namespace SmartSql.Deserializer
57
{
68
public class DeserializerFactory : IDeserializerFactory
79
{
8-
private readonly IDataReaderDeserializer _defaultDeser;
9-
private readonly IDataReaderDeserializer _valueTypeDeser;
10-
private readonly IDataReaderDeserializer _dynamicDeser;
11-
private readonly IDataReaderDeserializer _multipleDeser;
12-
private readonly IDataReaderDeserializer _valueTupleDeser;
10+
private readonly IList<IDataReaderDeserializer> _deserCache = new List<IDataReaderDeserializer>();
11+
private readonly IDataReaderDeserializer _Default_Deserializer;
1312
public DeserializerFactory()
1413
{
15-
_valueTypeDeser = new ValueTypeDeserializer();
16-
_defaultDeser = new EntityDeserializer();
17-
_dynamicDeser = new DynamicDeserializer();
18-
_multipleDeser = new MultipleResultDeserializer(this);
19-
_valueTupleDeser = new ValueTupleDeserializer(this);
14+
_Default_Deserializer = new EntityDeserializer();
2015
}
2116

22-
public IDataReaderDeserializer Get(ExecutionContext executionContext, Type resultType = null)
17+
public IDataReaderDeserializer Get(ExecutionContext executionContext, Type resultType = null, bool isMultiple = false)
2318
{
24-
if (executionContext.Request.MultipleResultMap != null)
25-
{
26-
return _multipleDeser;
27-
}
28-
if (resultType == null)
29-
{
30-
resultType = executionContext.Result.ResultType;
31-
}
19+
resultType = resultType ?? executionContext.Result.ResultType;
3220

33-
return Get(resultType);
21+
var deser = _deserCache.FirstOrDefault(d => d.CanDeserialize(executionContext, resultType, isMultiple));
22+
return deser ?? _Default_Deserializer;
3423
}
3524

36-
public IDataReaderDeserializer Get(Type resultType)
25+
public void Add(IDataReaderDeserializer deserializer)
3726
{
38-
if (CommonType.IsValueTuple(resultType))
39-
{
40-
return _valueTupleDeser;
41-
}
42-
43-
if (resultType.IsValueType || resultType == CommonType.String)
44-
{
45-
return _valueTypeDeser;
46-
}
47-
return resultType == CommonType.Object ? _dynamicDeser : _defaultDeser;
27+
_deserCache.Add(deserializer);
4828
}
4929
}
5030
}

src/SmartSql/Deserializer/DynamicDeserializer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
using System.Dynamic;
55
using System.Linq;
66
using System.Threading.Tasks;
7+
using SmartSql.Reflection.TypeConstants;
78

89
namespace SmartSql.Deserializer
910
{
1011
public class DynamicDeserializer : IDataReaderDeserializer
1112
{
13+
public bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false)
14+
{
15+
return resultType == CommonType.Object;
16+
}
17+
1218
public TResult ToSinge<TResult>(ExecutionContext executionContext)
1319
{
1420
var dataReader = executionContext.DataReaderWrapper;

src/SmartSql/Deserializer/EntityDeserializer.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace SmartSql.Deserializer
1717
{
1818
public class EntityDeserializer : IDataReaderDeserializer
1919
{
20+
public bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false)
21+
{
22+
return true;
23+
}
24+
2025
public TResult ToSinge<TResult>(ExecutionContext executionContext)
2126
{
2227
var dataReader = executionContext.DataReaderWrapper;

src/SmartSql/Deserializer/IDataReaderDeserializer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace SmartSql.Deserializer
1010
{
1111
public interface IDataReaderDeserializer : IDataReaderDeserializerAsync
1212
{
13+
bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false);
1314
TResult ToSinge<TResult>(ExecutionContext executionContext);
1415
IList<TResult> ToList<TResult>(ExecutionContext executionContext);
1516
}

src/SmartSql/Deserializer/IDeserializerFactory.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ namespace SmartSql.Deserializer
66
{
77
public interface IDeserializerFactory
88
{
9-
IDataReaderDeserializer Get(ExecutionContext executionContext, Type resultType = null);
10-
IDataReaderDeserializer Get(Type resultType);
11-
9+
IDataReaderDeserializer Get(ExecutionContext executionContext, Type resultType = null, bool isMultiple = false);
10+
void Add(IDataReaderDeserializer deserializer);
1211
}
1312
}

src/SmartSql/Deserializer/MultipleResultDeserializer.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public MultipleResultDeserializer(IDeserializerFactory deserializerFactory)
1919
_deserializerFactory = deserializerFactory;
2020
_setAccessorFactory = new EmitSetAccessorFactory();
2121
}
22+
23+
public bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false)
24+
{
25+
return isMultiple;
26+
}
27+
2228
public TResult ToSinge<TResult>(ExecutionContext executionContext)
2329
{
2430
TResult result = default;
@@ -27,7 +33,7 @@ public TResult ToSinge<TResult>(ExecutionContext executionContext)
2733
var multipleResultMap = executionContext.Request.MultipleResultMap;
2834
if (multipleResultMap.Root != null)
2935
{
30-
var deser = _deserializerFactory.Get(executionContext.Result.ResultType);
36+
var deser = _deserializerFactory.Get(executionContext, executionContext.Result.ResultType);
3137
result = deser.ToSinge<TResult>(executionContext);
3238
if (result == null)
3339
{
@@ -44,7 +50,7 @@ public TResult ToSinge<TResult>(ExecutionContext executionContext)
4450
#region Set Muti Property
4551
var propertyInfo = resultType.GetProperty(resultMap.Property);
4652
var setProperty = _setAccessorFactory.Create(propertyInfo);
47-
var deser = _deserializerFactory.Get(propertyInfo.PropertyType);
53+
var deser = _deserializerFactory.Get(executionContext, propertyInfo.PropertyType);
4854
var resultMapResult = TypeDeserializer.Deserialize(propertyInfo.PropertyType, deser, executionContext);
4955
setProperty(result, resultMapResult);
5056
#endregion
@@ -64,7 +70,7 @@ public async Task<TResult> ToSingeAsync<TResult>(ExecutionContext executionConte
6470
var multipleResultMap = executionContext.Request.MultipleResultMap;
6571
if (multipleResultMap.Root != null)
6672
{
67-
var deser = _deserializerFactory.Get(executionContext.Result.ResultType);
73+
var deser = _deserializerFactory.Get(executionContext);
6874
result = deser.ToSinge<TResult>(executionContext);
6975
if (result == null)
7076
{
@@ -81,8 +87,8 @@ public async Task<TResult> ToSingeAsync<TResult>(ExecutionContext executionConte
8187
#region Set Muti Property
8288
var propertyInfo = resultType.GetProperty(resultMap.Property);
8389
var setProperty = _setAccessorFactory.Create(propertyInfo);
84-
var deser = _deserializerFactory.Get(propertyInfo.PropertyType);
85-
90+
var deser = _deserializerFactory.Get(executionContext, propertyInfo.PropertyType);
91+
8692
var resultMapResult = TypeDeserializer.Deserialize(propertyInfo.PropertyType, deser, executionContext);
8793
setProperty(result, resultMapResult);
8894
#endregion

src/SmartSql/Deserializer/ValueTupleDeserializer.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Threading.Tasks;
34
using SmartSql.Exceptions;
45
using SmartSql.Reflection;
6+
using SmartSql.Reflection.TypeConstants;
57

68
namespace SmartSql.Deserializer
79
{
@@ -14,6 +16,11 @@ public ValueTupleDeserializer(IDeserializerFactory deserializerFactory)
1416
_deserializerFactory = deserializerFactory;
1517
}
1618

19+
public bool CanDeserialize(ExecutionContext executionContext, Type resultType, bool isMultiple = false)
20+
{
21+
return CommonType.IsValueTuple(resultType);
22+
}
23+
1724
public TResult ToSinge<TResult>(ExecutionContext executionContext)
1825
{
1926
var valueTupleType = typeof(TResult);

0 commit comments

Comments
 (0)