Skip to content

Commit

Permalink
fix TypeDeserializer bug when resultType is String
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahoo-Wang committed Jun 18, 2020
1 parent 283efb7 commit fdfdb6f
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 104 deletions.
2 changes: 1 addition & 1 deletion build/version.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<VersionMajor>4</VersionMajor>
<VersionMinor>1</VersionMinor>
<VersionPatch>54</VersionPatch>
<VersionPatch>55</VersionPatch>
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
</PropertyGroup>
</Project>
2 changes: 2 additions & 0 deletions sample/SmartSql.Sample.AspNetCore/Maps/User.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<MultipleResultMap Id="QueryByPageResult">
<Result Property="List"/>
<Result Property="Total"/>
<Result Property="UserName"/>
</MultipleResultMap>
</MultipleResultMaps>
<Statements>
Expand Down Expand Up @@ -96,6 +97,7 @@
Limit @PageSize Offset 0;
Select Count(1) From T_User T
<Include RefId="QueryParams"/>;
Select 'SmartSql';
</Statement>

<!--获取记录数-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
<PackageReference Include="SkyAPM.Agent.AspNetCore" Version="0.9.0" />
<PackageReference Include="SkyAPM.Diagnostics.SmartSql" Version="0.9.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
<PackageReference Include="System.Data.SQLite" Version="1.0.111" />
</ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions sample/SmartSql.Sample.AspNetCore/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Diagnostics.SmartSql;
using SkyApm.Utilities.DependencyInjection;
using SmartSql.Cache.Sync;
using SmartSql.ConfigBuilder;
using SmartSql.DIExtension;
Expand All @@ -29,6 +31,7 @@ public Startup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// services.AddSkyApmExtensions().AddSmartSql();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services
.AddSmartSql((sp, builder) =>
Expand Down
189 changes: 96 additions & 93 deletions src/SmartSql.Test.Unit/SmartSqlMapConfig.xml
Original file line number Diff line number Diff line change
@@ -1,96 +1,99 @@
<?xml version="1.0" encoding="utf-8" ?>
<SmartSqlMapConfig xmlns="http://SmartSql.net/schemas/SmartSqlMapConfig.xsd">
<Settings IgnoreParameterCase="false" ParameterPrefix="$" IsCacheEnabled="true" EnablePropertyChangedTrack="true" IgnoreDbNull="true"/>
<Properties>
<!-- <Property Name="Redis" Value="localhost"/>-->
<Property Name="DbProvider" Value="MsSqlServer"/>
<Property Name="ConnectionString" Value="Data Source=.;Initial Catalog=SmartSqlTestDB;Integrated Security=True"/>
<Property Name="JsonTypeHandler`" Value="SmartSql.TypeHandler.JsonTypeHandler`1,SmartSql.TypeHandler"/>
<Property Name="JsonTypeHandler" Value="SmartSql.TypeHandler.JsonTypeHandler,SmartSql.TypeHandler"/>
<Property Name="ScriptBuilder" Value="SmartSql.ScriptTag.ScriptBuilder,SmartSql.ScriptTag"/>
<Property Name="RedisCacheProvider" Value="SmartSql.Cache.Redis.RedisCacheProvider,SmartSql.Cache.Redis"/>
</Properties>
<AutoConverters>
<AutoConverter Name="NoneConverter">
<Tokenizer Name="None"/>
<Converter Name="None"/>
</AutoConverter>
<AutoConverter Name="Default" Default="true">
<Tokenizer Name="Default"/>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="PascalConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value="" />
<Property Name="Delimiter" Value="_" />
<Property Name="UppercaseSplit" Value="false" />
</Properties>
</Tokenizer>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="DelimiterConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value="col_" />
<Property Name="Delimiter" Value="_" />
<Property Name="UppercaseSplit" Value="true" />
</Properties>
</Tokenizer>
<Converter Name="Delimiter">
<Properties>
<Property Name="Prefix" Value="Col_" />
<Property Name="Delimiter" Value="_"/>
<Property Name="Mode" Value="FirstUpper"/>
</Properties>
</Converter>
</AutoConverter>
</AutoConverters>
<Database>
<!-- MsSqlServer: Microsoft.Data.SqlClient , SqlServer: System.Data.SqlClinet -->
<DbProvider Name="${DbProvider}"/>
<Write Name="WriteDB" ConnectionString="${ConnectionString}"/>
<Read Name="ReadDb-1" ConnectionString="${ConnectionString}" Weight="100"/>
<Read Name="ReadDb-2" ConnectionString="${ConnectionString}" Weight="100"/>
</Database>
<TypeHandlers>
<TypeHandler PropertyType="SmartSql.Test.Entities.UserInfo,SmartSql.Test" Type="${JsonTypeHandler`}">
<Properties>
<Property Name="DateFormat" Value="yyyy-MM-dd mm:ss"/>
<Property Name="NamingStrategy" Value="Camel"/>
</Properties>
</TypeHandler>
<TypeHandler Name="AnsiStringTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiString"/>
</Properties>
</TypeHandler>
<TypeHandler Name="AnsiStringFixedLengthTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiStringFixedLength"/>
</Properties>
</TypeHandler>
<TypeHandler Name="Json" Type="${JsonTypeHandler}"></TypeHandler>
</TypeHandlers>
<TagBuilders>
<TagBuilder Name="Script" Type="${ScriptBuilder}"/>
</TagBuilders>
<IdGenerators>
<IdGenerator Name="SnowflakeId" Type="SnowflakeId">
<Properties>
<Property Name="WorkerIdBits" Value="9"/>
<Property Name="WorkerId" Value="511"/>
<Property Name="Sequence" Value="14"/>
</Properties>
</IdGenerator>
<IdGenerator Name="DbSequence" Type="DbSequence">
<Properties>
<Property Name="Step" Value="10"/>
<Property Name="SequenceSql" Value="Select Next Value For IdSequence;"/>
</Properties>
</IdGenerator>
</IdGenerators>
<SmartSqlMaps>
<SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap>
</SmartSqlMaps>
<Settings IgnoreParameterCase="false" ParameterPrefix="$" IsCacheEnabled="true" EnablePropertyChangedTrack="true"
IgnoreDbNull="true"/>
<Properties>
<!-- <Property Name="Redis" Value="localhost"/>-->
<Property Name="DbProvider" Value="MsSqlServer"/>
<Property Name="ConnectionString"
Value="Data Source=.;Initial Catalog=SmartSqlTestDB;Integrated Security=True"/>
<Property Name="JsonTypeHandler`" Value="SmartSql.TypeHandler.JsonTypeHandler`1,SmartSql.TypeHandler"/>
<Property Name="JsonTypeHandler" Value="SmartSql.TypeHandler.JsonTypeHandler,SmartSql.TypeHandler"/>
<Property Name="ScriptBuilder" Value="SmartSql.ScriptTag.ScriptBuilder,SmartSql.ScriptTag"/>
<Property Name="RedisCacheProvider" Value="SmartSql.Cache.Redis.RedisCacheProvider,SmartSql.Cache.Redis"/>
</Properties>
<AutoConverters>
<AutoConverter Name="NoneConverter">
<Tokenizer Name="None"/>
<Converter Name="None"/>
</AutoConverter>
<AutoConverter Name="Default" Default="true">
<Tokenizer Name="Default"/>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="PascalConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value=""/>
<Property Name="Delimiter" Value="_"/>
<Property Name="UppercaseSplit" Value="false"/>
</Properties>
</Tokenizer>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="DelimiterConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value="col_"/>
<Property Name="Delimiter" Value="_"/>
<Property Name="UppercaseSplit" Value="true"/>
</Properties>
</Tokenizer>
<Converter Name="Delimiter">
<Properties>
<Property Name="Prefix" Value="Col_"/>
<Property Name="Delimiter" Value="_"/>
<Property Name="Mode" Value="FirstUpper"/>
</Properties>
</Converter>
</AutoConverter>
</AutoConverters>
<Database>
<!-- MsSqlServer: Microsoft.Data.SqlClient , SqlServer: System.Data.SqlClinet -->
<DbProvider Name="${DbProvider}"/>
<Write Name="WriteDB" ConnectionString="${ConnectionString}"/>
<Read Name="ReadDb-1" ConnectionString="${ConnectionString}" Weight="100"/>
<Read Name="ReadDb-2" ConnectionString="${ConnectionString}" Weight="100"/>
</Database>
<TypeHandlers>
<TypeHandler PropertyType="SmartSql.Test.Entities.UserInfo,SmartSql.Test" Type="${JsonTypeHandler`}">
<Properties>
<Property Name="DateFormat" Value="yyyy-MM-dd mm:ss"/>
<Property Name="NamingStrategy" Value="Camel"/>
</Properties>
</TypeHandler>
<TypeHandler Name="AnsiStringTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiString"/>
</Properties>
</TypeHandler>
<TypeHandler Name="AnsiStringFixedLengthTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiStringFixedLength"/>
</Properties>
</TypeHandler>
<TypeHandler Name="Json" Type="${JsonTypeHandler}"></TypeHandler>

</TypeHandlers>
<TagBuilders>
<TagBuilder Name="Script" Type="${ScriptBuilder}"/>
</TagBuilders>
<IdGenerators>
<IdGenerator Name="SnowflakeId" Type="SnowflakeId">
<Properties>
<Property Name="WorkerIdBits" Value="9"/>
<Property Name="WorkerId" Value="511"/>
<Property Name="Sequence" Value="14"/>
</Properties>
</IdGenerator>
<IdGenerator Name="DbSequence" Type="DbSequence">
<Properties>
<Property Name="Step" Value="10"/>
<Property Name="SequenceSql" Value="Select Next Value For IdSequence;"/>
</Properties>
</IdGenerator>
</IdGenerators>
<SmartSqlMaps>
<SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap>
</SmartSqlMaps>
</SmartSqlMapConfig>
3 changes: 2 additions & 1 deletion src/SmartSql.Test/DTO/GetByPageResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public class GetByPageResponse<TItem>
{
public IEnumerable<TItem> List { get; set; }
public int Total { get; set; }
public String UserName { get; set; }
}
}
}
22 changes: 13 additions & 9 deletions src/SmartSql/Deserializer/TypeDeserializer.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using SmartSql.Configuration;
using SmartSql.Reflection.TypeConstants;
using SmartSql.Utils;

namespace SmartSql.Deserializer
{
public class TypeDeserializer
{
public static object Deserialize(Type resultType, IDataReaderDeserializer deserializer, ExecutionContext executionContext)
public static object Deserialize(Type resultType, IDataReaderDeserializer deserializer,
ExecutionContext executionContext)
{
return GetImpl(resultType)(deserializer, executionContext);
}

private static Func<IDataReaderDeserializer, ExecutionContext, object> GetImpl(Type resultType)
{
return CacheUtil<TypeDeserializer, Type, Func<IDataReaderDeserializer, ExecutionContext, object>>
.GetOrAdd(resultType, CreateImpl);
.GetOrAdd(resultType, CreateImpl);
}

private static Func<IDataReaderDeserializer, ExecutionContext, object> CreateImpl(Type resultType)
{
var dynamicMethod = new DynamicMethod("CreateGetResult_" + Guid.NewGuid().ToString("N"), CommonType.Object, new[] { IDataReaderDeserializerType.Type, ExecutionContextType.Type });
var dynamicMethod = new DynamicMethod("CreateGetResult_" + Guid.NewGuid().ToString("N"), CommonType.Object,
new[] {IDataReaderDeserializerType.Type, ExecutionContextType.Type});
var ilGen = dynamicMethod.GetILGenerator();
ilGen.LoadArg(0);
ilGen.LoadArg(1);
MethodInfo deserMethod;
if (CommonType.IEnumerable.IsAssignableFrom(resultType))
if (
CommonType.IEnumerable.IsAssignableFrom(resultType)
&& resultType != CommonType.String)
{
var listItemType = resultType.GenericTypeArguments[0];
deserMethod = IDataReaderDeserializerType.Method.MakeGenericToList(listItemType);
Expand All @@ -38,13 +39,16 @@ private static Func<IDataReaderDeserializer, ExecutionContext, object> CreateImp
{
deserMethod = IDataReaderDeserializerType.Method.MakeGenericToSingle(resultType);
}

ilGen.Callvirt(deserMethod);
if (resultType.IsValueType)
{
ilGen.Box(resultType);
}

ilGen.Return();
return (Func<IDataReaderDeserializer, ExecutionContext, object>)dynamicMethod.CreateDelegate(typeof(Func<IDataReaderDeserializer, ExecutionContext, object>));
return (Func<IDataReaderDeserializer, ExecutionContext, object>) dynamicMethod.CreateDelegate(
typeof(Func<IDataReaderDeserializer, ExecutionContext, object>));
}
}
}
}

0 comments on commit fdfdb6f

Please sign in to comment.