更新代码

This commit is contained in:
qaz734913414 2023-12-28 08:50:27 +08:00
parent 1d727a09ef
commit 1f5525b793
127 changed files with 11723 additions and 3401 deletions

View File

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>0.9.6.7</Version>
<TargetFrameworks>net8.0</TargetFrameworks>
<Version>0.9.6.5</Version>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Authors>QQ:761716178</Authors>
<Company>QQ:761716178</Company>
<Product>QQ:761716178 跨平台UI框架</Product>
@ -12,7 +13,7 @@
<PackageId>Xhm.CPF.Linux</PackageId>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFrameworks>net8.0</TargetFrameworks>
<Product>QQ:761716178 跨平台UI框架</Product>
<Version>0.9.6.7</Version>
<Version>0.9.6.6</Version>
<PackageId>Xhm.CPF.Mac</PackageId>
<Description>CPF(Cross platform UI framework) QQ:761716178 跨平台UI框架 http://cpf.cskin.net/</Description>
<Copyright>Copyright (c) 2020 by http://cpf.cskin.net/</Copyright>
@ -11,7 +11,6 @@
<Authors>QQ:761716178</Authors>
<Company>QQ:761716178</Company>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@ -1,16 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>net8.0</TargetFrameworks>
<Product>QQ:761716178 跨平台UI框架</Product>
<Version>0.9.6.7</Version>
<Version>0.9.6.6</Version>
<PackageId>Xhm.CPF.Skia</PackageId>
<Description>CPF(Cross platform UI framework) QQ:761716178 跨平台UI框架 http://cpf.cskin.net/</Description>
<Copyright>Copyright (c) 2020 by http://cpf.cskin.net/</Copyright>
<PackageReleaseNotes>CPF(Cross platform UI framework) QQ:761716178 跨平台UI框架 http://cpf.cskin.net/</PackageReleaseNotes>
<Authors>QQ:761716178</Authors>
<Company>QQ:761716178</Company>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -31,7 +30,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="1.68.3" />
<PackageReference Include="SkiaSharp" Version="2.88.6" />
</ItemGroup>
<ItemGroup>

View File

@ -52,11 +52,6 @@ namespace CPF.Skia
public SkiaDrawingContext(IRenderTarget target, SkiaDrawingFactory drawingFactory)
{
this.drawingFactory = drawingFactory;
if (target.Width < 1 || target.Height < 1)
{
Debug.WriteLine("绘图表面为空");
Console.WriteLine("绘图表面为空");
}
if (!target.CanUseGPU || !drawingFactory.UseGPU)
{
IntPtr hdc = IntPtr.Zero;

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;netstandard2.0;net5</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<Product>QQ:761716178 跨平台UI框架</Product>
<Version>0.9.6.7</Version>
<Version>0.9.6.6</Version>
<PackageId>Xhm.CPF.Windows</PackageId>
<Description>CPF(Cross platform UI framework) QQ:761716178 跨平台UI框架 http://cpf.cskin.net/</Description>
<PackageProjectUrl>http://cpf.cskin.net/</PackageProjectUrl>
@ -12,6 +12,8 @@
<Authors>QQ:761716178</Authors>
<Company>QQ:761716178</Company>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>$(NoWarn);SYSLIB0011</NoWarn>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -55,7 +57,6 @@
<PropertyGroup>
<DefineConstants Condition="'$(TargetFramework)'=='net40'">Net4</DefineConstants>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
</Project>

View File

@ -226,16 +226,16 @@ namespace CPF
{
Value = value;
}
///// <summary>
///// 设置和绑定附加属性
///// </summary>
///// <param name="value"></param>
///// <param name="sourceProperty"></param>
///// <param name="binding"></param>
//public AttachedDescribe(object value, string sourceProperty, BindingMode binding) : base(sourceProperty, binding)
//{
// Value = value;
//}
/// <summary>
/// 设置和绑定附加属性
/// </summary>
/// <param name="value"></param>
/// <param name="sourceProperty"></param>
/// <param name="binding"></param>
public AttachedDescribe(object value, string sourceProperty, BindingMode binding) : base(sourceProperty, binding)
{
Value = value;
}
/// <summary>
/// 设置和绑定附加属性
/// </summary>
@ -257,17 +257,17 @@ namespace CPF
{
Value = value;
}
///// <summary>
///// 设置和绑定附加属性
///// </summary>
///// <param name="value"></param>
///// <param name="source"></param>
///// <param name="sourceProperty"></param>
///// <param name="convert"></param>
//public AttachedDescribe(object value, object source, string sourceProperty, Func<object, object> convert) : base(source, sourceProperty, convert)
//{
// Value = value;
//}
/// <summary>
/// 设置和绑定附加属性
/// </summary>
/// <param name="value"></param>
/// <param name="source"></param>
/// <param name="sourceProperty"></param>
/// <param name="convert"></param>
public AttachedDescribe(object value, object source, string sourceProperty, Func<object, object> convert) : base(source, sourceProperty, convert)
{
Value = value;
}
/// <summary>
/// 设置和绑定附加属性
/// </summary>
@ -308,10 +308,6 @@ namespace CPF
{
Value = value;
}
public AttachedDescribe(object value, Func<UIElement, UIElement> find, string sourceProperty, BindingMode binding, Func<object, object> convert, Func<object, object> convertBack, Action<Binding, object, Exception> SourceToTargetError, Action<Binding, object, Exception> TargetToSourceError) : base(find, sourceProperty, binding, convert, convertBack, SourceToTargetError, TargetToSourceError)
{
Value = value;
}
public object Value { get; set; }

View File

@ -1009,7 +1009,7 @@ namespace CPF
public bool ReadValue<T>(out T value) where T : struct
{
value = default;
#if NET40
#if Net4
int len = Marshal.SizeOf(typeof(T));
#else
int len = Marshal.SizeOf<T>();
@ -1018,7 +1018,7 @@ namespace CPF
{
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(data, 0, ptr, len);
#if NET40
#if Net4
value = (T)Marshal.PtrToStructure(ptr, typeof(T));
#else
value = Marshal.PtrToStructure<T>(ptr);

View File

@ -18,11 +18,11 @@ namespace CPF
PropertyName = sourceProperty;
}
//public BindingDescribe(string sourceProperty, BindingMode binding)
//{
// PropertyName = sourceProperty;
// BindingMode = binding;
//}
public BindingDescribe(string sourceProperty, BindingMode binding)
{
PropertyName = sourceProperty;
BindingMode = binding;
}
/// <summary>
/// 设置绑定
/// </summary>
@ -39,24 +39,25 @@ namespace CPF
/// 设置绑定
/// </summary>
/// <param name="source">如果是int或者byte0是自己1是Parent2是Parent.Parent....</param>
/// <param name="source"></param>
/// <param name="sourceProperty"></param>
public BindingDescribe(object source, string sourceProperty)
{
PropertyName = sourceProperty;
Source = source;
}
///// <summary>
///// 设置绑定
///// </summary>
///// <param name="source">如果是int或者byte0是自己1是Parent2是Parent.Parent....</param>
///// <param name="sourceProperty"></param>
///// <param name="convert"></param>
//public BindingDescribe(object source, string sourceProperty, Func<object, object> convert)
//{
// PropertyName = sourceProperty;
// Source = source;
// Convert = convert;
//}
/// <summary>
/// 设置绑定
/// </summary>
/// <param name="source">如果是int或者byte0是自己1是Parent2是Parent.Parent....</param>
/// <param name="sourceProperty"></param>
/// <param name="convert"></param>
public BindingDescribe(object source, string sourceProperty, Func<object, object> convert)
{
PropertyName = sourceProperty;
Source = source;
Convert = convert;
}
/// <summary>
/// 设置绑定
/// </summary>
@ -79,7 +80,7 @@ namespace CPF
/// <param name="binding"></param>
/// <param name="convert"></param>
/// <param name="convertBack"></param>
public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func<object, object> convert = null, Func<object, object> convertBack = null)
public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func<object, object> convert, Func<object, object> convertBack)
{
BindingMode = binding;
PropertyName = sourceProperty;
@ -97,7 +98,7 @@ namespace CPF
/// <param name="convertBack"></param>
/// <param name="SourceToTargetError"></param>
/// <param name="TargetToSourceError"></param>
public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func<object, object> convert = null, Func<object, object> convertBack = null, Action<Binding, object, Exception> SourceToTargetError = null, Action<Binding, object, Exception> TargetToSourceError = null)
public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func<object, object> convert, Func<object, object> convertBack, Action<Binding, object, Exception> SourceToTargetError, Action<Binding, object, Exception> TargetToSourceError)
{
BindingMode = binding;
PropertyName = sourceProperty;
@ -108,23 +109,11 @@ namespace CPF
this.TargetToSourceError = TargetToSourceError;
}
public BindingDescribe(Func<UIElement, UIElement> find, string sourcePropertyName, BindingMode bindingMode = BindingMode.OneWay, Func<object, object> convert = null, Func<object, object> convertBack = null, Action<Binding, object, Exception> SourceToTargetError = null, Action<Binding, object, Exception> TargetToSourceError = null)
public BindingDescribe(CommandDescribe command)
{
BindingMode = bindingMode;
PropertyName = sourcePropertyName;
Source = find;
//Find = find;
Convert = convert;
ConvertBack = convertBack;
this.SourceToTargetError = SourceToTargetError;
this.TargetToSourceError = TargetToSourceError;
Command = command;
}
//public BindingDescribe(CommandDescribe command)
//{
// Command = command;
//}
/// <summary>
/// 数据绑定的转换
/// </summary>
@ -400,7 +389,6 @@ namespace CPF
//}
public BindingMode BindingMode { get; set; } = BindingMode.OneWay;
public object Source { get; set; }
//public Func<UIElement, UIElement> Find { get; set; }
public Action<Binding, object, Exception> SourceToTargetError { get; set; }
public Action<Binding, object, Exception> TargetToSourceError { get; set; }

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<Authors>QQ:761716178</Authors>
<Company>QQ:761716178</Company>
<Product>QQ:761716178 跨平台UI框架</Product>
<Description>CPF(Cross platform UI framework) QQ:761716178 跨平台UI框架 http://cpf.cskin.net/</Description>
<Version>0.9.6.7</Version>
<Version>0.9.6.6</Version>
<LangVersion>9.0</LangVersion>
<PackageId>Xhm.CPF</PackageId>
<PackageProjectUrl></PackageProjectUrl>
@ -50,7 +50,7 @@
<Compile Remove="Drawing\FormattedText.cs" />
<Compile Remove="Drawing\Matrix - 复制.cs" />
<Compile Remove="Effects\OpacityMaskEffect.cs" />
<Compile Remove="NET40\CallerMember.cs" />
<Compile Remove="Net4\CallerMember.cs" />
<Compile Remove="Platform\IScreenImpl.cs" />
<Compile Remove="Reflection\Accessor.cs" />
<Compile Remove="Reflection\ConstructorInvoker.cs" />
@ -95,7 +95,7 @@
<EmbeddedResource Include="loading.gif" />
</ItemGroup>
<PropertyGroup>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<DefineConstants Condition="'$(TargetFramework)'=='net40'">Net4</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net40'">
<PackageReference Include="AsyncBridge" Version="0.3.1" />

View File

@ -225,7 +225,7 @@ namespace CPF.Controls
/// <summary>
/// 布局好的行
/// </summary>
#if NET40
#if Net4
public IList<TextLine> Lines
{
get { return codeTextView.Lines; }
@ -269,7 +269,7 @@ namespace CPF.Controls
if (render)
{
render = false;
#if NET40
#if Net4
await TaskEx.Delay(30);
#else
await Task.Delay(30);
@ -285,7 +285,7 @@ namespace CPF.Controls
Cancellation = new CancellationTokenSource();
}
var ks = KeywordsStyles.ToArray();
#if NET40
#if Net4
var styles = await TaskEx.Run(() => CodeTextView.RenderKeywords(Cancellation.Token, ks, codeTextView.Text));
#else
var styles = await Task.Run(() => CodeTextView.RenderKeywords(Cancellation.Token, ks, codeTextView.Text));

View File

@ -742,7 +742,7 @@ namespace CPF.Controls
/// <summary>
/// 布局好的行
/// </summary>
#if NET40
#if Net4
public IList<TextLine> Lines
{
get { return lines; }

View File

@ -860,7 +860,7 @@ namespace CPF.Controls
List<object> list = new List<object>();
foreach (var item in SelectedIndexs)
{
if (item >= items.Count || item < 0)
if (item >= items.Count && item < 0)
{
continue;
}

View File

@ -273,7 +273,7 @@ namespace CPF.Controls
/// <param name="propertyName">缓存的属性</param>
/// <param name="descending">降序</param>
public void Sort(Comparison<object> comparison, string propertyName = null, bool descending = false)
{
{//选择排序
Events[nameof(StartSort)]?.Invoke(this, EventArgs.Empty);
this.comparison = comparison;

View File

@ -686,7 +686,6 @@ namespace CPF.Controls
/// <summary>
/// 响应布局元素的可见性
/// </summary>
[Flags]
public enum RVisible : byte
{
Hidden = 0,

View File

@ -174,7 +174,7 @@ namespace CPF.Controls
{
try
{
#if NET40
#if Net4
if (item.CanRead && item.GetGetMethod().GetParameters().Length == 0)
{
var v = item.GetValue(ele, null);

View File

@ -223,10 +223,6 @@ namespace CPF
{
Bindings.Add(propertyName, value.PropertyName, layer1, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError);
}
else if (value.Source is Func<UIElement, UIElement> find)
{
Bindings.Add(propertyName, value.PropertyName, find, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError);
}
else
{
Bindings.Add(propertyName, value.PropertyName, value.Source, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError);
@ -3044,32 +3040,7 @@ namespace CPF
public void Sort(IComparer<T> comparison)
{
//Array.Sort(_items, 0, Count, comparison);
InsertSort(_items, Count, comparison);
}
//插入排序法
void InsertSort(T[] array, int count, IComparer<T> comparison)
{
//for循环i作为指针进行从左到右扫描数据的工作
//指针i从1开始扫描因为i=0时指针左侧无元素
for (int i = 1; i < count; i++)
{
//temp作为指针键值
var temp = array[i];
//新建变量j从i开始向左扫描已经有序的元素并与temp比较
//若temp小于扫描元素则将j指针元素向右移位腾出空间
int j = i;
while (j > 0 && comparison.Compare(array[j - 1], temp) > 0)//array[j - 1] > temp
{
array[j] = array[j - 1];
j--;
}
//循环完成后将temp放在j指针位置完成本次插入
array[j] = temp;
}
Array.Sort(_items, 0, Count, comparison);
}
}

View File

@ -30,17 +30,9 @@ namespace CPF.Design
}
public static CommandMessage<T> DeserializeWithString(string json)
{
var t = typeof(T);
try
{
var obj = JsonSerializer.ToObject<CommandMessage<T>>(json);
return obj;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("JSON异常" + json + " \n\n" + t.Name + " " + e);
}
return default;
var obj = JsonSerializer.ToObject<CommandMessage<T>>(json);
return obj;
//return default;
}
/// <summary>

View File

@ -45,7 +45,7 @@ namespace CPF.Design
}
Screen[] screens = new Screen[] { new Screen(new Rect(0, 0, 1920, 1080), new Rect(0, 0, 1920, 1080), true) };
#if NET40
#if Net4
public override IList<Screen> GetAllScreen()
{
return screens;

View File

@ -211,7 +211,7 @@ namespace CPF.Documents
/// <summary>
/// 布局好的行
/// </summary>
#if NET40
#if Net4
public IList<TextLine> Lines
{
get { return lines; }

View File

@ -17,7 +17,7 @@ namespace CPF.Documents
/// <summary>
/// 布局好的行
/// </summary>
#if NET40
#if Net4
IList<TextLine> Lines { get; }
#else
IReadOnlyList<TextLine> Lines { get; }

View File

@ -35,30 +35,32 @@ namespace CPF.Drawing
return Color.ToString();
}
//protected override void Disposing()
//{
// //usings.Remove(this);
// disposes.Add(this);
//}
protected override void Disposing()
{
//usings.Remove(this);
disposes.Add(this);
}
internal static SolidColorBrush Create(Color color)
internal static SolidColorBrush Creaate(Color color)
{
SolidColorBrush sb;
//if (disposes.Count == 0)
//{
sb = new SolidColorBrush(color);
//}
//else
//{
// sb = disposes[disposes.Count - 1];
// disposes.RemoveAt(disposes.Count - 1);
// sb.Color = color;
// sb.IsDisposed = false;
//}
if (disposes.Count == 0)
{
sb = new SolidColorBrush(color);
}
else
{
sb = disposes[disposes.Count - 1];
disposes.RemoveAt(disposes.Count - 1);
sb.Color = color;
sb.IsDisposed = false;
}
//usings.Add(sb);
return sb;
}
//static List<SolidColorBrush> disposes = new List<SolidColorBrush>();
static List<SolidColorBrush> disposes = new List<SolidColorBrush>();
//static HashSet<SolidColorBrush> usings = new HashSet<SolidColorBrush>();
}
}

View File

@ -0,0 +1,22 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 别名,标记于字段或属性上的特性
/// Alias,Characteristics marked on fields or property
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class AliasAttribute : Attribute
{
internal string _name { get; set; }
/// <summary>
/// Structural aliases
/// </summary>
/// <param name="name"></param>
public AliasAttribute(string name)
{
_name = name;
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 被标记的元素,在序列化或反序列化时时将被忽略
/// Marked elements are ignored when serialized or deserialized
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class IgnoreKeyAttribute : Attribute
{
}
}

View File

@ -0,0 +1,14 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 当被标记元素的值为默认值时,序列化时将忽略其元素
/// When the value of the tagged element is the default, its element is ignored when serialized
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class |
AttributeTargets.Struct)]
public class IgnoreDefaultValueAttribute : Attribute
{
}
}

View File

@ -0,0 +1,24 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 对Model进行Json反序列化时指定一个构造函数
/// Specify a constructor for Json deserialization of Model
/// </summary>
[AttributeUsage(AttributeTargets.Constructor)]
public class JsonDeserializeCtorAttribute : Attribute
{
internal object[] _args;
/// <summary>
/// 反序列化时的指定构造函数以及参数args必须和构造函数参数匹配
/// Deserializing the specified constructor and parameters, args must match the constructor parameters
/// </summary>
/// <param name="args">该构造函数的参数,The parameters of the constructor</param>
public JsonDeserializeCtorAttribute(params object[] args)
{
_args = args;
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 序列化仅包含此元素,和Ignore相反
/// Serialization contains only this element, as opposed to Ignore
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonOnlyIncludeAttribute : Attribute
{
}
}

View File

@ -0,0 +1,22 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 元素排序,标记于字段或属性上的特性
/// Element sort, a feature marked on a field or property
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonOrderAttribute: Attribute
{
internal ushort _orderNum { get; set; }
/// <summary>
/// JsonOrder
/// </summary>
/// <param name="orderNum">Order number</param>
public JsonOrderAttribute(ushort orderNum)
{
_orderNum = orderNum;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Reflection;
namespace CPF.Json
{
/// <summary>
/// 对Model的值格式化器特性,可标注于字段,属性,结构或类上,(字段/属性) 优先级大于 (结构/类)
/// Value formatter features of Model can be labeled on fields, properties, structures or classes with priority of
/// (fields/properties) over (structures/classes)
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class |
AttributeTargets.Struct)]
public abstract class ValueFormatAttribute : Attribute
{
#region pregenerated metas
internal static MethodInfo _WriteValueFormat = typeof(ValueFormatAttribute).GetMethod(nameof(WriteValueFormat));
internal static MethodInfo _ReadValueFormat = typeof(ValueFormatAttribute).GetMethod(nameof(ReadValueFormat));
#endregion
/// <summary>
/// 序列化时 - Model的Value的格式化器
/// Serialization time - Value formatter for Model
/// </summary>
/// <param name="value">需要被格式化的源元素数据,Source element data that needs to be formatted</param>
/// <param name="type">值的类型,The type of the value</param>
/// <param name="handler">用于提供一些配置选项,Used to provide some configuration options</param>
/// <param name="isValueFormat">决定最终是否进行值格式化,Determines whether the value is ultimately formatted</param>
/// <returns>格式化后的结果,Formatted results</returns>
public virtual string WriteValueFormat(object value,Type type, JsonSerializerHandler handler, out bool isValueFormat)
{
isValueFormat = false;
return null;
}
/// <summary>
/// 反序列化时 - Model的Value的格式化器
/// When deserializing - Value formatter for Model
/// </summary>
/// <param name="value">从Json字符串中读取的匹配字符串,Matched strings read from Json strings</param>
/// <param name="type">值的类型,The type of the value</param>
/// <param name="handler">用于提供一些配置选项,Used to provide some configuration options</param>
/// <param name="isValueFormat">决定最终是否进行值格式化,Determines whether the value is ultimately formatted</param>
/// <returns>格式化后的结果,Formatted results</returns>
public virtual object ReadValueFormat(string value,Type type, JsonDeserializeHandler handler, out bool isValueFormat)
{
isValueFormat = false;
return null;
}
}
}

View File

@ -0,0 +1,53 @@
using CPF.Json.Deserialize;
using System;
using System.Reflection;
namespace CPF.Json
{
/// <summary>
/// 类型解析错误
/// Json Deserialization TypeResolution Exception
/// </summary>
public class JsonDeserializationTypeResolutionException : Exception
{
#region pregenerated metas
internal static ConstructorInfo _JsonDeserializationTypeResolutionExceptionMsgCtor =
typeof(JsonDeserializationTypeResolutionException).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null);
internal static ConstructorInfo _JsonDeserializationTypeResolutionExceptionCtor =
typeof(JsonDeserializationTypeResolutionException).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(JsonReader), typeof(Type) }, null);
#endregion
internal JsonDeserializationTypeResolutionException() : base("Json deserialization type parsing error")
{
}
internal JsonDeserializationTypeResolutionException(string msg) : base(
$"Json deserialization type parsing error : {msg}")
{
}
internal JsonDeserializationTypeResolutionException(Type t) : base(
$"Json deserialization {t.Name} type parsing error")
{
}
internal JsonDeserializationTypeResolutionException(JsonReader reader, Type t) : base(
$"Json deserialization {t.Name} type parsing error ,An error occurred on symbol {reader.Length - reader.Remaining-1} , it's { reader[reader.Length - reader.Remaining-1]}")
{
}
internal JsonDeserializationTypeResolutionException(JsonReader reader, Type t, string msg) : base(
$"Json deserialization {t.Name} type parsing error ,An error occurred on symbol {reader.Length - reader.Remaining-1} , {msg}")
{
}
internal JsonDeserializationTypeResolutionException(Type t, string msg) : base(
$"Json deserialization {t.Name} type parsing error , {msg}")
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 不受支持的解析类型
/// Unsupported parse type
/// </summary>
public class JsonNoSupportedDeserializeTypeException : Exception
{
internal JsonNoSupportedDeserializeTypeException(string msg) : base("Json Deserialize Unsupported type : " + msg)
{
}
internal JsonNoSupportedDeserializeTypeException(Type t) : base("Json Deserialize Unsupported type : " + t.Name)
{
}
internal JsonNoSupportedDeserializeTypeException(Type t, string msg) : base("Json Deserialize Unsupported type : " + t.Name + " , " + msg)
{
}
}
}

View File

@ -0,0 +1,68 @@
using CPF.Json.Deserialize;
using System;
using System.Reflection;
namespace CPF.Json
{
/// <summary>
/// 错误的json字符
/// Json Wrong Character
/// </summary>
public class JsonWrongCharacterException : Exception
{
#region pregenerated metas
internal static ConstructorInfo _JsonWrongCharacterExceptionCtor =
typeof(JsonWrongCharacterException).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
new[] { typeof(JsonReader) }, null);
#endregion
internal JsonWrongCharacterException() : base("Incorrect JSON format")
{
}
internal JsonWrongCharacterException(string msg) : base("Incorrect JSON format : " + msg)
{
}
internal JsonWrongCharacterException(int index) : base(
$"Incorrect JSON format : An error occurred on symbol {index} ")
{
}
internal JsonWrongCharacterException(int index, string correctString) : base(
$"Incorrect JSON format : An error occurred on symbol {index} , {correctString}")
{
}
internal JsonWrongCharacterException(int index, char correctChar, char errorChar) : base(
$"Incorrect JSON format : An error occurred on symbol {index} , It should be {correctChar}, but it's actually {errorChar}")
{
}
internal JsonWrongCharacterException(JsonReader reader) : this(
reader.Length - reader.Remaining)
{
}
internal JsonWrongCharacterException( JsonReader reader, string correctString) : this(
reader.Length - reader.Remaining, correctString)
{
}
internal JsonWrongCharacterException(JsonReader reader, char correctChar) : this(
reader.Length - reader.Remaining, correctChar,
reader[reader.Length - reader.Remaining])
{
}
}
}

View File

@ -1,73 +0,0 @@
using System.Text;
namespace CPF.Json
{
internal static class Formatter
{
public static string Indent = " ";
public static void AppendIndent(StringBuilder sb, int count)
{
for (; count > 0; --count) sb.Append(Indent);
}
public static string PrettyPrint(string input)
{
var output = new StringBuilder();
int depth = 0;
int len = input.Length;
char[] chars = input.ToCharArray();
for (int i = 0; i < len; ++i)
{
char ch = chars[i];
if (ch == '\"') // found string span
{
bool str = true;
while (str)
{
output.Append(ch);
ch = chars[++i];
if (ch == '\\')
{
output.Append(ch);
ch = chars[++i];
}
else if (ch == '\"')
str = false;
}
}
switch (ch)
{
case '{':
case '[':
output.Append(ch);
output.AppendLine();
AppendIndent(output, ++depth);
break;
case '}':
case ']':
output.AppendLine();
AppendIndent(output, --depth);
output.Append(ch);
break;
case ',':
output.Append(ch);
output.AppendLine();
AppendIndent(output, depth);
break;
case ':':
output.Append(" : ");
break;
default:
if (!char.IsWhiteSpace(ch))
output.Append(ch);
break;
}
}
return output.ToString();
}
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Runtime.CompilerServices;
namespace CPF.Json.Deserialize
{
internal class BaseTypeResolve: DefaultJsonResolve
{
[FuncLable(FuncType.BaseType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static Exception ReadException(JsonReader reader, JsonDeserializeHandler handler)
{
if (reader.ReadNullOrObjLeft())
return null;
if (reader.ReadBoolObjRight())
return new Exception();
string source = null, message = null, helpLink = null;
int i = 1;
char c = ' ';
while (i-- > 0)
{
reader.ReadQuotes();
switch (handler.Option.JsonCharacterReadState)
{
case JsonCharacterReadStateEnum.None:
c = reader.GetChar();
break;
case JsonCharacterReadStateEnum.InitialUpper:
c = char.ToUpper(reader.GetChar());
break;
case JsonCharacterReadStateEnum.InitialLower:
c = char.ToLower(reader.GetChar());
break;
}
switch (c)
{
case 'S':
c = reader.GetChar();
if (c == 'o' && reader.StrCompair("urce\""))
{
reader.ReadColon();
source = PrimitiveResolve.ReadEscapeString(reader, handler);
}
else if (c == 't' && reader.StrCompair("ackTrace\""))
{
//只读
reader.ReadColon();
PrimitiveResolve.ReadEscapeString(reader, handler);
}
else
throw new Exception();
break;
case 'M':
{
if (reader.StrCompair("essage\""))
{
reader.ReadColon();
message = PrimitiveResolve.ReadEscapeString(reader, handler);
}
else
throw new Exception();
break;
}
case 'H':
{
if ( reader.StrCompair("elpLink\""))
{
reader.ReadColon();
helpLink = PrimitiveResolve.ReadEscapeString(reader, handler);
}
else
throw new Exception();
break;
}
default:
throw new Exception();
}
if (reader.ReadBoolComma())
i++;
}
var exception = message != null ? new Exception(message) : new Exception();
exception.Source = source;
exception.HelpLink = helpLink;
return exception;
}
[FuncLable(FuncType.BaseType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static Type ReadType(JsonReader reader, JsonDeserializeHandler handler)
{
var typeName = PrimitiveResolve.ReadEscapeString(reader, handler);
return typeName != null ? Type.GetType(typeName) : null;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace CPF.Json.Deserialize
{
internal class SpecialConditionsResolve : DefaultJsonResolve
{
#region pregenerated metas
internal static MethodInfo _ReadAvoidNull = typeof(SpecialConditionsResolve).GetMethod(nameof(ReadAvoidNull), BindingFlags.NonPublic | BindingFlags.Static);
internal static MethodInfo _ReadNullable = typeof(SpecialConditionsResolve).GetMethod(nameof(ReadNullable), BindingFlags.NonPublic | BindingFlags.Static);
internal static MethodInfo _ReadEnum = typeof(SpecialConditionsResolve).GetMethod(nameof(ReadEnum), BindingFlags.NonPublic | BindingFlags.Static);
#endregion
//---------Avoid
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void ReadAvoidNull(JsonReader reader)
{
char c = reader.BeforAnnotation();
if (c == 'n' && reader.StrCompair("ull"))
return;
if (c == '{' && reader.GetChar() == '}')
return;
throw new JsonWrongCharacterException(reader);
}
//---------T?
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static T? ReadNullable<T>(JsonReader reader, JsonDeserializeHandler handler) where T : struct
{
var c = reader.BeforAnnotation();
if (c == 'n')
{
if (reader.StrCompair("ull"))
return null;
throw new JsonDeserializationTypeResolutionException(typeof(T?));
}
else
{
reader.RollbackChar();
return (T?)ResolveProvider<T>.InvokeGet(reader, handler);
}
}
//---------Enum
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static object ReadEnum(JsonReader reader, JsonDeserializeHandler handler)
{
var c = reader.BeforAnnotation();
var t = handler.Types.Dequeue();
if (c == '"')
{
reader.RollbackChar();
var str = reader.ReadString();
return Enum.Parse(t, str);
}
if (c >= '0' && c <= '9')// byte、sbyte、short、ushort、int、uint、long 、ulong default ->int
{
reader.RollbackChar();
var basicType = Enum.GetUnderlyingType(t);
if (basicType == typeof(long))
return Enum.ToObject(t, PrimitiveResolve.ReadLong(reader, handler));
else if (basicType == typeof(ulong))
return Enum.ToObject(t, PrimitiveResolve.ReadULong(reader, handler));
else if (basicType == typeof(uint))
return Enum.ToObject(t, PrimitiveResolve.ReadUInt(reader, handler));
else
return Enum.ToObject(t, PrimitiveResolve.ReadInt(reader, handler));
}
throw new JsonDeserializationTypeResolutionException(reader, t);
}
}
}

View File

@ -0,0 +1,414 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Text;
namespace CPF.Json.Deserialize
{
internal class SpecialTypeResolve : DefaultJsonResolve
{
//---------Special
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static DataTable ReadDataTable(JsonReader reader, JsonDeserializeHandler handler)
{
//[{ \"Id\":1 , \"Name\":\"ss\" }]
if (reader.ReadNullOrArrayLeft())
return null;
DataTable dt = new DataTable();
int moveNext = 1;
while (moveNext-- > 0)
{
reader.ReadObjLeft();
DataRow dr = dt.NewRow();
int move = 1;
while (move-- > 0)
{
string columnName = PrimitiveResolve.ReadEscapeString(reader,handler);
reader.ReadColon();
DataColumn column = dt.Columns[columnName];
if (column == null)
{
column = new DataColumn(columnName, typeof(object));
dt.Columns.Add(column);
}
object rowValue = PrimitiveResolve.ReadObject(reader, handler);
dr[columnName] = rowValue;
if (reader.ReadBoolComma())
move++;
}
dr.EndEdit();
dt.Rows.Add(dr);
reader.ReadObjRight();
if (reader.ReadBoolComma())
moveNext++;
}
reader.ReadArrayRight();
return dt;
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static DBNull ReadDBNull(JsonReader reader, JsonDeserializeHandler handler)
{
char c = reader.BeforAnnotation();
if (c == 'n' && reader.StrCompair("ull"))
return DBNull.Value;
throw new JsonDeserializationTypeResolutionException(typeof(DBNull));
}
private static ResolveDelegate<byte[]> byteArray;
private static readonly object ObjLock = new object();
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static byte[] ReadBytes(JsonReader reader, JsonDeserializeHandler handler)
{
char c = reader.BeforAnnotation();
if (c == 'n' && reader.StrCompair("ull"))
return null;
else if (c == '[')
{
reader.RollbackChar();
if (byteArray == null)
{
lock (ObjLock)
{
if (byteArray == null)
byteArray = BuildFactory.Build<byte[]>(DeserializeBuildTypeEnum.Array, typeof(byte[]));
}
}
return byteArray(reader, handler);
}
else
{
reader.RollbackChar();
return Convert.FromBase64String(PrimitiveResolve.ReadEscapeString(reader,handler));
}
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static Guid ReadGuid(JsonReader reader, JsonDeserializeHandler handler)
{
var c = reader.BeforAnnotation();
if (c == '"')
{
if (reader.Remaining > 36)
{
// 1314FAD4-7505-439D-ABD2-DBD89242928C
// 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
//
// Guid is guaranteed to be a 36 character string
// Bytes are in a different order than you might expect
// For: 35 91 8b c9 - 19 6d - 40 ea - 97 79 - 88 9d 79 b7 53 f0
// Get: C9 8B 91 35 6D 19 EA 40 97 79 88 9D 79 B7 53 F0
// Ix: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var asStruct = new GuidStruct
{
B03 = ReadGuidByte(reader),
B02 = ReadGuidByte(reader),
B01 = ReadGuidByte(reader),
B00 = ReadGuidByte(reader)
};
c = reader.GetChar();
if (c != '-')
throw new JsonWrongCharacterException(reader, "Guid format error");
asStruct.B05 = ReadGuidByte(reader);
asStruct.B04 = ReadGuidByte(reader);
c = reader.GetChar();
if (c != '-')
throw new JsonWrongCharacterException(reader, "Guid format error");
asStruct.B07 = ReadGuidByte(reader);
asStruct.B06 = ReadGuidByte(reader);
c = reader.GetChar();
if (c != '-')
throw new JsonWrongCharacterException(reader, "Guid format error");
asStruct.B08 = ReadGuidByte(reader);
asStruct.B09 = ReadGuidByte(reader);
c = reader.GetChar();
if (c != '-')
throw new JsonWrongCharacterException(reader, "Guid format error");
asStruct.B10 = ReadGuidByte(reader);
asStruct.B11 = ReadGuidByte(reader);
asStruct.B12 = ReadGuidByte(reader);
asStruct.B13 = ReadGuidByte(reader);
asStruct.B14 = ReadGuidByte(reader);
asStruct.B15 = ReadGuidByte(reader);
if (reader.GetChar() == '"')
return asStruct.Value;
}
}
throw new JsonDeserializationTypeResolutionException(reader, typeof(Guid));
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static Uri ReadUri(JsonReader reader, JsonDeserializeHandler handler)
{
char c = reader.BeforAnnotation();
if (c == 'n' && reader.StrCompair("ull"))
return null;
else
{
reader.RollbackChar();
return new Uri(PrimitiveResolve.ReadEscapeString(reader,handler));
}
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static NameValueCollection ReadNameValueCollection(JsonReader reader, JsonDeserializeHandler handler)
{
if (reader.ReadNullOrObjLeft())
return null;
NameValueCollection nameValueCollection = new NameValueCollection();
int moveNext = 1;
while (moveNext-- > 0)
{
var key = PrimitiveResolve.ReadEscapeString( reader, handler);
reader.ReadColon();
var value = PrimitiveResolve.ReadEscapeString(reader, handler);
nameValueCollection.Add(key, value);
if (reader.ReadBoolComma())
moveNext++;
}
reader.ReadObjRight();
return nameValueCollection;
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static StringDictionary ReadStringDictionary(JsonReader reader, JsonDeserializeHandler handler)
{
if (reader.ReadNullOrObjLeft())
return null;
StringDictionary nameValueCollection = new StringDictionary();
int moveNext = 1;
while (moveNext-- > 0)
{
var key = PrimitiveResolve.ReadEscapeString(reader, handler);
reader.ReadColon();
var value = PrimitiveResolve.ReadEscapeString(reader, handler);
nameValueCollection.Add(key, value);
if (reader.ReadBoolComma())
moveNext++;
}
reader.ReadObjRight();
return nameValueCollection;
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static ExpandoObject ReadExpandoObject(JsonReader reader, JsonDeserializeHandler handler)
{
if (reader.ReadNullOrObjLeft())
return null;
ExpandoObject obj = new ExpandoObject();
var dic = (IDictionary<string, object>)obj;
int moveNext = 1;
while (moveNext-- > 0)
{
var key = PrimitiveResolve.ReadEscapeString(reader, handler);
reader.ReadColon();
var value = PrimitiveResolve.ReadObject(reader, handler);
dic.Add(key, value);
if (reader.ReadBoolComma())
moveNext++;
}
reader.ReadObjRight();
return obj;
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static StringBuilder ReadStringBuilder(JsonReader reader, JsonDeserializeHandler handler)
{
var c = reader.BeforAnnotation();
if (c == '"')
{
int start = reader.Length - reader.Remaining;
int length = 0;
StringBuilder charBufferSb = new StringBuilder();
while (reader.Remaining > 0)
{
c = reader.GetChar();
if (c == '"')//end
{
if (length > 0)
{
if (reader.Json != null)
charBufferSb.Append(reader.Json, start, length);
else
charBufferSb.Append(reader.Buffer, start, length);
}
return charBufferSb;
}
if (c != '\\')
{
++length;
continue;
}
if (length > 0)
{
if (reader.Json != null)
charBufferSb.Append(reader.Json, start, length);
else
charBufferSb.Append(reader.Buffer, start, length);
start += length;
length = 0;
}
/*
string s = "a\\\\b";
string s = "a\\u005cb";
*/
start += 2;
if (reader.Remaining < 1)
throw new JsonDeserializationTypeResolutionException(reader, typeof(string));
c = reader.GetChar();
switch (c)
{
case '"': charBufferSb.Append('"'); continue;
case '\\': charBufferSb.Append('\\'); continue;
case '/': charBufferSb.Append('/'); continue;
case 'b': charBufferSb.Append('\b'); continue;
case 'f': charBufferSb.Append('\f'); continue;
case 'n': charBufferSb.Append('\n'); continue;
case 'r': charBufferSb.Append('\r'); continue;
case 't': charBufferSb.Append('\t'); continue;
case 'u':
{ // \\uXXXX
if (reader.Remaining > 4)//4+'"'
{
int idx = charBufferSb.Length;
charBufferSb.Append(reader.GetChar());
charBufferSb.Append(reader.GetChar());
charBufferSb.Append(reader.GetChar());
charBufferSb.Append(reader.GetChar());
int unicode = (((((charBufferSb[idx].CharToNumber() * 16) + charBufferSb[++idx].CharToNumber()) * 16) + charBufferSb[++idx].CharToNumber()) * 16) + charBufferSb[++idx].CharToNumber();
charBufferSb.Remove(idx - 3, 4);
charBufferSb.Append((char)unicode);
start += 4;
continue;
}
throw new JsonWrongCharacterException(reader, "It should be four hexadecimal digits , such as \\uFFFF");
}
default:
throw new JsonWrongCharacterException(reader, c);
}
}
}
else if (c == 'n' && reader.StrCompair("ull"))
return null;
throw new JsonDeserializationTypeResolutionException(reader, typeof(string));
}
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static BitArray ReadBitArray(JsonReader reader, JsonDeserializeHandler handler)
{
if (reader.ReadNullOrArrayLeft())
return null;
if (reader.ReadBoolArrayRight())
return new BitArray(0);
bool[] values = new bool[reader.GetArrayLength(handler)];
for (int i = 0; i < values.Length; i++)
{
values[i] = PrimitiveResolve.ReadBool(reader, handler);
if (i != values.Length - 1)
reader.ReadComma();
}
reader.ReadArrayRight();
return new BitArray(values);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static byte ReadGuidByte(JsonReader reader)
{
int a = reader.GetChar();
if (!((a >= '0' && a <= '9') || (a >= 'A' && a <= 'F') || (a >= 'a' && a <= 'f')))
throw new JsonWrongCharacterException(reader, "Guid format error");
int b = reader.GetChar();
if (!((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')))
throw new JsonWrongCharacterException(reader, "Guid format error");
if (a <= '9')
a -= '0';
else
{
if (a <= 'F')
a -= ('A' - 10);
else
a -= ('a' - 10);
}
if (b <= '9')
b -= '0';
else
{
if (b <= 'F')
b -= ('A' - 10);
else
b -= ('a' - 10);
}
return (byte)(a * 16 + b);
}
}
}

View File

@ -0,0 +1,576 @@
using System;
using System.Runtime.CompilerServices;
namespace CPF.Json.Deserialize
{
internal class TimeSpanResolve : DefaultJsonResolve
{
[FuncLable(FuncType.SameType)]
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static unsafe TimeSpan ReadTimeSpan( JsonReader reader, JsonDeserializeHandler handler)
{
/*
\"P10675199DT2H48M5.4775807S\" => ISO
\"10675199.02:48:05.4775807\" => Microsoft
*/
reader.ReadQuotes();
char* ip = reader.Pointer;
char c = ip[0];
if (c == '-')
c = ip[1];
if (c == 'P')
return _ReadISO8601TimeSpan(reader);
else
return ReadMicrosoftTimeSpan(reader);
}
static readonly ulong MinTicks = (ulong)-TimeSpan.MinValue.Ticks;
static readonly ulong MaxTicks = (ulong)TimeSpan.MaxValue.Ticks;
static readonly double[] DivideFractionBy =
{
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000
};
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static unsafe TimeSpan ReadMicrosoftTimeSpan(JsonReader reader)
{
char* ip = reader.Pointer;
int start = reader.Remaining;
int strLen = -1;
for (int z = 0; z < reader.Remaining; z++)
{
if (ip[z] == '"')
{
strLen = z;
break;
}
}
if (strLen < 1)
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan));
reader.Pointer += strLen + 1;// "
reader.Remaining -= strLen + 1;// "
int days, hours, minutes, seconds, fraction;
days = hours = minutes = seconds = fraction = 0;
bool isNegative, pastDays, pastHours, pastMinutes, pastSeconds;
isNegative = pastDays = pastHours = pastMinutes = pastSeconds = false;
var ixOfLastPeriod = -1;
var part = 0;
int i;
if (ip[0] == '-')
{
isNegative = true;
i = 1;
}
else
{
i = 0;
}
for (; i < strLen; i++)
{
var c = ip[i];
if (c == '.')
{
ixOfLastPeriod = i;
if (!pastDays)
{
days = part;
part = 0;
pastDays = true;
continue;
}
if (!pastSeconds)
{
seconds = part;
part = 0;
pastSeconds = true;
continue;
}
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan));
}
if (c == ':')
{
if (!pastHours)
{
hours = part;
part = 0;
pastHours = true;
continue;
}
if (!pastMinutes)
{
minutes = part;
part = 0;
pastMinutes = true;
continue;
}
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan));
}
if (c < '0' || c > '9')
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan));
}
part *= 10;
part += c - '0';
}
if (!pastSeconds)
{
seconds = part;
pastSeconds = true;
}
else
{
fraction = part;
}
if (!pastHours || !pastMinutes || !pastSeconds)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Missing required portion of TimeSpan");
}
var msInt = 0;
if (fraction != 0)
{
var sizeOfFraction = strLen - (ixOfLastPeriod + 1);
if (sizeOfFraction > 7)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Fractional part of TimeSpan too large");
}
var fracOfSecond = part / DivideFractionBy[sizeOfFraction - 1];
var ms = fracOfSecond * 1000.0;
msInt = (int)ms;
if (ms > msInt)
return TimeSpan.Parse(reader.SubString(reader.Length - start, strLen));
}
var ret = new TimeSpan(days, hours, minutes, seconds, msInt);
if (isNegative)
{
ret = ret.Negate();
}
return ret;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static unsafe TimeSpan _ReadISO8601TimeSpan(JsonReader reader)
{
const ulong ticksPerDay = 864000000000;
const ulong ticksPerWeek = ticksPerDay * 7;
const ulong ticksPerMonth = ticksPerDay * 30;
const ulong ticksPerYear = ticksPerDay * 365;
// Format goes like so:
// - (-)P(([n]Y)([n]M)([n]D))(T([n]H)([n]M)([n]S))
// - P[n]W
char* ip = reader.Pointer;
int len = -1;
for (int i = 0; i < reader.Remaining; i++)
{
if (ip[i] == '"')
{
len = i;
break;
}
}
if (len < 1)
throw new JsonWrongCharacterException(reader);
reader.Pointer += len + 1;
reader.Remaining -= len + 1;
var ix = 0;
var isNegative = false;
var c = ip[ix];
if (c == '-')
{
isNegative = true;
ix++;
}
if (ix >= len)
{
throw new JsonWrongCharacterException("Expected P, instead TimeSpan string ended");
}
c = ip[ix];
if (c != 'P')
{
throw new JsonWrongCharacterException("Expected P, found " + c.ToString());
}
ix++; // skip 'P'
var hasTimePart = ISO8601TimeSpan_ReadDatePart(ip, len, ref ix, out long year, out long month, out long week, out long day);
if (week != -1 && (year != -1 || month != -1 || day != -1))
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Week part of TimeSpan defined along with one or more of year, month, or day");
}
if (week != -1 && hasTimePart)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "TimeSpans with a week defined cannot also have a time defined");
}
if (year == -1) year = 0;
if (month == -1) month = 0;
if (week == -1) week = 0;
if (day == -1) day = 0;
ulong timeTicks;
if (hasTimePart)
{
ix++; // skip 'T'
ISO8601TimeSpan_ReadTimePart(ip, len, ref ix, out timeTicks);
}
else
{
timeTicks = 0;
}
ulong ticks = 0;
if (year != 0)
{
ticks += ((ulong)year) * ticksPerYear;
}
if (month != 0)
{
// .NET (via XmlConvert) converts months to years
// This isn't inkeeping with the spec, but of the bad choices... I choose this one
var yearsFromMonths = ((ulong)month) / 12;
var monthsAfterYears = ((ulong)month) % 12;
ticks += yearsFromMonths * ticksPerYear + monthsAfterYears * ticksPerMonth;
}
if (week != 0)
{
// ISO8601 defines weeks as 7 days, so don't convert weeks to months or years (even if that may seem more sensible)
ticks += ((ulong)week) * ticksPerWeek;
}
ticks += ((ulong)day) * ticksPerDay + timeTicks;
if (ticks >= MaxTicks && !isNegative)
{
return TimeSpan.MaxValue;
}
if (ticks >= MinTicks && isNegative)
{
return TimeSpan.MinValue;
}
var ret = new TimeSpan((long)ticks);
if (isNegative)
{
ret = ret.Negate();
}
return ret;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static unsafe bool ISO8601TimeSpan_ReadDatePart(char* ip, int strLen, ref int ix, out long year, out long month, out long week, out long day)
{
year = month = week = day = -1;
bool yearSeen, monthSeen, weekSeen, daySeen;
yearSeen = monthSeen = weekSeen = daySeen = false;
while (ix != strLen)
{
if (ip[ix] == 'T')
{
return true;
}
var part = ISO8601TimeSpan_ReadPart(ip, strLen, ref ix, out int whole, out int fraction, out int fracLen);
if (fracLen != 0)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Fractional values are not supported in the year, month, day, or week parts of an ISO8601 TimeSpan");
}
if (part == 'Y')
{
if (yearSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Year part of TimeSpan seen twice");
}
if (monthSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Year part of TimeSpan seen after month already parsed");
}
if (daySeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Year part of TimeSpan seen after day already parsed");
}
year = whole;
yearSeen = true;
continue;
}
if (part == 'M')
{
if (monthSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Month part of TimeSpan seen twice");
}
if (daySeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Month part of TimeSpan seen after day already parsed");
}
month = whole;
monthSeen = true;
continue;
}
if (part == 'W')
{
if (weekSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Week part of TimeSpan seen twice");
}
week = whole;
weekSeen = true;
continue;
}
if (part == 'D')
{
if (daySeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Day part of TimeSpan seen twice");
}
day = whole;
daySeen = true;
continue;
}
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Expected Y, M, W, or D but found: " + part);
}
return false;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static unsafe char ISO8601TimeSpan_ReadPart(char* ip, int strLen, ref int ix, out int whole, out int fraction, out int fracLen)
{
var part = 0;
while (true)
{
var c = ip[ix];
if (c == '.' || c == ',')
{
whole = part;
break;
}
ix++;
if (c < '0' || c > '9' || ix == strLen)
{
whole = part;
fraction = 0;
fracLen = 0;
return c;
}
part *= 10;
part += c - '0';
}
var ixOfPeriod = ix;
ix++; // skip the '.' or ','
part = 0;
while (true)
{
var c = ip[ix];
ix++;
if (c < '0' || c > '9' || ix == strLen)
{
fraction = part;
fracLen = ix - 1 - (ixOfPeriod + 1);
return c;
}
part *= 10;
part += c - '0';
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static unsafe void ISO8601TimeSpan_ReadTimePart(char* str, int strLen, ref int ix, out ulong ticks)
{
const ulong ticksPerHour = 36000000000;
const ulong ticksPerMinute = 600000000;
const ulong ticksPerSecond = 10000000;
ticks = 0;
bool hourSeen, minutesSeen, secondsSeen;
hourSeen = minutesSeen = secondsSeen = false;
var fracSeen = false;
while (ix != strLen)
{
if (fracSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Expected Time part of TimeSpan to end");
}
char part = ISO8601TimeSpan_ReadPart(str, strLen, ref ix, out int whole, out int fraction, out int fracLen);
if (fracLen != 0)
{
fracSeen = true;
}
if (part == 'H')
{
if (hourSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Hour part of TimeSpan seen twice");
}
if (minutesSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Hour part of TimeSpan seen after minutes already parsed");
}
if (secondsSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Hour part of TimeSpan seen after seconds already parsed");
}
ticks += (ulong)whole * ticksPerHour + ISO8601TimeSpan_FractionToTicks(9, fraction * 36, fracLen);
hourSeen = true;
continue;
}
if (part == 'M')
{
if (minutesSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Minute part of TimeSpan seen twice");
}
if (secondsSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Minute part of TimeSpan seen after seconds already parsed");
}
ticks += (ulong)whole * ticksPerMinute + ISO8601TimeSpan_FractionToTicks(8, fraction * 6, fracLen);
minutesSeen = true;
continue;
}
if (part == 'S')
{
if (secondsSeen)
{
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Seconds part of TimeSpan seen twice");
}
ticks += (ulong)whole * ticksPerSecond + ISO8601TimeSpan_FractionToTicks(7, fraction, fracLen);
secondsSeen = true;
continue;
}
throw new JsonDeserializationTypeResolutionException(typeof(TimeSpan), "Expected H, M, or S but found: " + part);
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static ulong ISO8601TimeSpan_FractionToTicks(int maxLen, int fraction, int fracLen)
{
if (fracLen == 0)
{
return 0;
}
if (fracLen > maxLen)
{
fraction /= (int)Pow10(fracLen - maxLen);
fracLen = maxLen;
}
return (ulong)(fraction * Pow10(maxLen - fracLen));
}
static readonly long[] PowersOf10 = {
1L,
10L,
100L,
1000L,
10000L,
100000L,
1000000L,
10000000L,
100000000L
};
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static long Pow10(int power)
{
if (power < PowersOf10.Length)
return PowersOf10[power];
return (long)Math.Pow(10, power);
}
}
}

View File

@ -0,0 +1,8 @@

namespace CPF.Json.Deserialize
{
internal class DefaultJsonResolve : JsonResolveBase
{
}
}

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Threading;
namespace CPF.Json.Deserialize
{
internal class DeserializeObjectJump
{
private static SpinLock _spinLock = new SpinLock();
private static readonly Dictionary<Type, Func<string, JsonDeserializeHandler, object>> JumpStringConvertDics =
new Dictionary<Type, Func<string, JsonDeserializeHandler, object>>();
private static readonly Dictionary<Type, Func<StreamReader, JsonDeserializeHandler, object>> JumpStreamConvertDics =
new Dictionary<Type, Func<StreamReader, JsonDeserializeHandler, object>>();
internal static object GetThreadSafetyJumpFunc(string json, Type t, JsonDeserializeHandler handler)
{
if (JumpStringConvertDics.TryGetValue(t, out var fc))
return fc(json, handler);
else
{
try
{
bool i = false;
_spinLock.Enter(ref i);
if (!JumpStringConvertDics.TryGetValue(t, out fc))
{
fc = GenerateJumpStringConvertFunc(t);
JumpStringConvertDics.Add(t, fc);
}
return fc(json, handler);
}
catch (Exception e)
{
throw e;
}
finally
{
_spinLock.Exit();
}
}
}
internal static object GetThreadSafetyJumpFunc(StreamReader stream, Type t, JsonDeserializeHandler handler)
{
if (JumpStreamConvertDics.TryGetValue(t, out var fc))
return fc(stream, handler);
else
{
try
{
bool i = false;
_spinLock.Enter(ref i);
if (!JumpStreamConvertDics.TryGetValue(t, out fc))
{
fc = GenerateJumpStreamConvertFunc(t);
JumpStreamConvertDics.Add(t, fc);
}
return fc(stream, handler);
}
catch (Exception e)
{
throw e;
}
finally
{
_spinLock.Exit();
}
}
}
internal static Func<string, JsonDeserializeHandler, object> GenerateJumpStringConvertFunc(Type t)
{
var genericType = typeof(ResolveProvider<>).MakeGenericType(t);
var jsonEx = Expression.Parameter(typeof(string), "json");
var handlerEx = Expression.Parameter(typeof(JsonDeserializeHandler), "handler");
var body = Expression.Convert(Expression.Call(genericType.GetMethod("Convert",System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Static,null, new Type[] { typeof(string), typeof(JsonDeserializeHandler) },null), jsonEx, handlerEx), typeof(object));
return Expression.Lambda<Func<string, JsonDeserializeHandler, object>>(body, jsonEx, handlerEx).Compile();
}
internal static Func<StreamReader, JsonDeserializeHandler, object> GenerateJumpStreamConvertFunc(Type t)
{
var genericType = typeof(ResolveProvider<>).MakeGenericType(t);
var jsonEx = Expression.Parameter(typeof(StreamReader), "reader");
var handlerEx = Expression.Parameter(typeof(JsonDeserializeHandler), "handler");
var body = Expression.Convert(Expression.Call(genericType.GetMethod("Convert", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static ,null,new Type[] { typeof(StreamReader), typeof(JsonDeserializeHandler) },null), jsonEx, handlerEx), typeof(object));
return Expression.Lambda<Func<StreamReader, JsonDeserializeHandler, object>>(body, jsonEx, handlerEx).Compile();
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using System.Linq.Expressions;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.Array)]
internal class ArrayBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type)
{
Type arrayItemType = type.GetElementType();
Expression[] methodListCall = new Expression[11];
LabelTarget returnTarget = Expression.Label(type, "returnLable");
/*
if (reader.ReadNullOrArrayLeft())
return null;
*/
Expression ifReadNullOrArrayLeftReturnNull = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrArrayLeft), Expression.Return(returnTarget, Expression.Constant(null, type)));
methodListCall[0] = ifReadNullOrArrayLeftReturnNull;
/*
int arrayLength=reader._GetArrayLength;
T[] array=new [arrayLength];
*/
ParameterExpression arrayLength = Expression.Variable(typeof(int), "arrayLength");
methodListCall[1] = Expression.Assign(arrayLength, Expression.Call(ExpressionMembers.Reader, JsonReader._GetArrayLength, ExpressionMembers.JsonDeserializeHandler));
NewExpression aryCtor = Expression.New(type.GetConstructors()[0], arrayLength);
ParameterExpression array = Expression.Variable(type, "array");
methodListCall[2] = Expression.Assign(array, aryCtor);
/*
if(arrayLength==0)
goto ReadArrayRightLabel;
*/
LabelTarget readArrayRightLabel = Expression.Label(typeof(void), "ReadArrayRightLabel");
methodListCall[3] = Expression.IfThen(Expression.Equal(arrayLength, Expression.Constant(0)), Expression.Goto(readArrayRightLabel));
/*
int moveNext=1;
*/
methodListCall[4] = ExpressionMembers.MoveNextAssignOne;
/*
int idx=0;
*/
ParameterExpression idx = Expression.Variable(typeof(int), "idx");
methodListCall[5] = Expression.Assign(idx, Expression.Constant(0));
/*
while(moveNext-->0)
{}
*/
LabelTarget loopBreak = Expression.Label("loopBreak");
LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement,
ReturnFunc<Expression>(() =>
{
Expression[] methodCall = new Expression[3];
/*
ary[idx]=item;
*/
methodCall[0] = Expression.Assign(Expression.ArrayAccess(array, idx), ExpressionMembers.GetMethodCall(arrayItemType));
/*
if(reader.ReadBoolComma()==true)
moveNext++;
*/
methodCall[1] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement;
/*
idx++;
*/
methodCall[2] = Expression.PostIncrementAssign(idx);
return Expression.Block(methodCall); ;
})
, Expression.Break(loopBreak)));
methodListCall[6] = Expression.Block(loopExpression, Expression.Label(loopBreak));
/*
ReadArrayRightLabel:
reader.ReadArrayRight()
*/
methodListCall[7] = Expression.Label(readArrayRightLabel);
methodListCall[8] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadArrayRight);
/*
return list;
*/
GotoExpression returnExpression = Expression.Return(returnTarget, array);
LabelExpression returnLabel = Expression.Label(returnTarget, array);
methodListCall[9] = returnExpression;
methodListCall[10] = returnLabel;
return Expression.Block(new[] { arrayLength, array, idx, ExpressionMembers.MoveNext }, methodListCall);
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
internal class BuildFactory
{
static BuildFactory()
{
var types = DeserializeBootTable.Table.ExpressionBuildTypes;
foreach (var item in types)
{
ExpressionBuildTypeAttribute expressionBuildTypeAttribute = (ExpressionBuildTypeAttribute)item.GetCustomAttributes(false).First(e => e.GetType() == typeof(ExpressionBuildTypeAttribute));
BuildMethodDics.Add(expressionBuildTypeAttribute._deserializeBuildType, item.GetMethod("Build", BindingFlags.Static | BindingFlags.NonPublic));
}
DeserializeBootTable.Table.ExpressionBuildTypes = null;
}
internal static Dictionary<Type, Expression> DEBUGSURVEY = new Dictionary<Type, Expression>();
static Dictionary<DeserializeBuildTypeEnum, MethodInfo> BuildMethodDics = new Dictionary<DeserializeBuildTypeEnum, MethodInfo>();
internal static ResolveDelegate<T> Build<T>(DeserializeBuildTypeEnum buildTypeEnum, params object[] objs)
{
ParameterExpression[] pars = { ExpressionMembers.Reader, ExpressionMembers.JsonDeserializeHandler };
BlockExpression body = (BlockExpression)BuildMethodDics[buildTypeEnum].Invoke(null, objs);
#if DEBUG
Type t = typeof(T);
DEBUGSURVEY.Add(t, body);
#endif
#if VIEW && NET45
var methodBuilder = typeBuilder.DefineMethod($"Deserialize_{typeof(T).Name}", System.Reflection.MethodAttributes.Static | System.Reflection.MethodAttributes.Public, typeof(T), new Type[] { typeof(JsonReader), typeof(JsonDeserializeHandler) });
Expression.Lambda<ResolveDelegate<T>>(
body, pars).CompileToMethod(methodBuilder);
#endif
ResolveDelegate<T> action = Expression.Lambda<ResolveDelegate<T>>(body, pars).Compile();
return action;
}
#if VIEW && NET45
#if DEBUG
static string suffix = "_Debug";
#else
static string suffix = "_Release";
#endif
static string name = $"Deserialize_CodeView{suffix}";
static System.Reflection.Emit.AssemblyBuilder assemblyBuilder = System.Reflection.Emit.AssemblyBuilder.DefineDynamicAssembly(new System.Reflection.AssemblyName(name), System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
static System.Reflection.Emit.ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, name + ".dll");
static System.Reflection.Emit.TypeBuilder typeBuilder = moduleBuilder.DefineType("Program");
#endif
internal static void Save()
{
#if VIEW && NET45
typeBuilder.CreateType();
assemblyBuilder.Save(name + ".dll");
#endif
}
}
}

View File

@ -0,0 +1,17 @@

namespace CPF.Json.Deserialize
{
internal enum DeserializeBuildTypeEnum
{
Dictionary,
Collection,
KeyValueObject,
CtorInject,
Array,
KeyValuePair,
Dynamic,
WrongGenericKey,
MultiArray,
Lazy
}
}

View File

@ -0,0 +1,107 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.Collection)]
internal class CollectionBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type defindType, Type instanceType, Type convertType,Type arrayItemType)
{
/*
//defind:IEnumerable<string> new: List<string> convert: List<string>
IEnumerable<string> li = new List<string>();
List<string> list = (List<string>)li;
//defind:ArrayList new:ArrayList convert: IList/ArrayList
ArrayList v = new ArrayList();
var df = (IList)v;
*/
Expression[] methodListCall = new Expression[9];
LabelTarget returnTarget = Expression.Label(defindType, "returnLable");
Expression ifReadNullOrArrayLeftReturnNull;
if (!defindType.IsValueType)
{
/*
if (reader.ReadNullOrArrayLeft())
return null;
*/
ifReadNullOrArrayLeftReturnNull = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrArrayLeft), Expression.Return(returnTarget, Expression.Constant(null, defindType)));
}
else
{
ifReadNullOrArrayLeftReturnNull = Expression.Call(ExpressionMembers.Reader,JsonReader._ReadArrayLeft);
}
methodListCall[0] = ifReadNullOrArrayLeftReturnNull;
/*
List<> list =new List<>();
*/
NewExpression listCtor = Expression.New(instanceType);
ParameterExpression list = Expression.Variable(defindType, "list");
methodListCall[1] = Expression.Assign(list, listCtor);
/*
if(reader.ReadBoolArrayRight)
return list;
*/
methodListCall[2] = (Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolArrayRight), Expression.Return(returnTarget, list)));
/*
ICollection<int> iCollec = (ICollection<int>)list;
iCollec.Add(ReadInt())
*/
MethodInfo iCollecAdd = convertType.GetMethod("Add",BindingFlags.Public|BindingFlags.Instance);
ParameterExpression iCollec = Expression.Variable(convertType, "iDic");
methodListCall[3] = Expression.Assign(iCollec, Expression.Convert(list, convertType));
/*
int moveNext=1;
*/
methodListCall[4] = ExpressionMembers.MoveNextAssignOne;
/*
while(moveNext-->0)
{}
*/
LabelTarget loopBreak = Expression.Label("loopBreak");
LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement,
ReturnFunc<Expression>(() =>
{
Expression[] methodCall = new Expression[2];
/*
list.Add(item);
*/
methodCall[0] = Expression.Call(iCollec, iCollecAdd, ExpressionMembers.GetMethodCall(arrayItemType));
/*
if(reader.ReadBoolComma()==true)
moveNext++;
*/
methodCall[1] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement;
return Expression.Block(methodCall); ;
})
, Expression.Break(loopBreak)));
methodListCall[5] = Expression.Block(loopExpression, Expression.Label(loopBreak));
/*
reader.ReadArrayRight()
*/
methodListCall[6] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadArrayRight);
/*
return list;
*/
GotoExpression returnExpression = Expression.Return(returnTarget, list);
LabelExpression returnLabel = Expression.Label(returnTarget, list);
methodListCall[7] = returnExpression;
methodListCall[8] = returnLabel;
return Expression.Block(new[] { iCollec, list, ExpressionMembers.MoveNext }, methodListCall);
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.CtorInject)]
internal class CtorInjectBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type, Type injectType, ConstructorInfo ctr)
{
LabelTarget returnTarget = Expression.Label(type, "returnLable");
ParameterExpression inject = Expression.Variable(injectType, "inject");
if (!type.IsValueType)
return Expression.Block(new[] { inject },
Expression.Assign(inject, ExpressionMembers.GetMethodCall(injectType)),//inject = Read<T>(); T-->
Expression.IfThenElse(
Expression.Equal(inject, Expression.Constant(null, injectType)),
Expression.Return(returnTarget, Expression.Constant(null, type)),
Expression.Return(returnTarget, Expression.Convert(Expression.New(ctr, inject), type))),
Expression.Label(returnTarget, Expression.Constant(null, type))
);
return Expression.Block(new[] { inject },
Expression.Assign(inject, ExpressionMembers.GetMethodCall(injectType)),
Expression.Return(returnTarget, Expression.Convert(Expression.New(ctr, inject), type)),
Expression.Label(returnTarget, Expression.Convert(Expression.New(ctr, inject), type)));
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.Dictionary)]
internal class DictionaryBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type defindType, Type instanceType, Type convertType,Type keyType,Type valueType)
{
/*
* defind:ExpandoObject new:ExpandoObject convert:IDictionary<string, object>
ExpandoObject ss = new ExpandoObject();
IDictionary<string, object> dic = (IDictionary<string, object>)ss;
hashtable
*/
Expression[] methodDictionaryCall = new Expression[9];
LabelTarget returnTarget = Expression.Label(defindType, "returnLable");
Expression ifReadNullOrObjLeftReturnNull;
if (!defindType.IsValueType)
/*
if (reader.ReadNullOrObjLeft())
return null;
*/
ifReadNullOrObjLeftReturnNull = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrObjLeft), Expression.Return(returnTarget, Expression.Constant(null, defindType)));
else
{
ifReadNullOrObjLeftReturnNull= Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjLeft);
}
methodDictionaryCall[0] = ifReadNullOrObjLeftReturnNull;
/*
Dictionary<> dictionary =new Dictionary<>();
*/
NewExpression dictionaryCtor = Expression.New(instanceType);
ParameterExpression dictionary = Expression.Variable(defindType, "dictionary");
methodDictionaryCall[1] = Expression.Assign(dictionary, dictionaryCtor);
/*
if(reader.ReadBoolObjRight)
return dictionary;
*/
methodDictionaryCall[2] = (Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolObjRight), Expression.Return(returnTarget, dictionary)));
/*
IDictionary iDic = dictionary;
IDictionary<,> iDic = dictionary;
*/
MethodInfo iDicAdd = convertType.GetMethod("Add");
ParameterExpression iDic = Expression.Variable(convertType, "iDic");
methodDictionaryCall[3] = Expression.Assign(iDic, Expression.Convert(dictionary, convertType));
/*
int moveNext=2;
*/
methodDictionaryCall[4] = ExpressionMembers.MoveNextAssignOne;
ParameterExpression key = Expression.Variable(keyType, "key");
ParameterExpression value = Expression.Variable(valueType, "value");
/*
while(moveNext-->0)
{}
*/
LabelTarget loopBreak = Expression.Label("loopBreak");
LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement,
ReturnFunc<Expression>(() =>
{
Expression[] methodCall = new Expression[5];
/*
ReadKey()
*/
methodCall[0] = ExpressionMembers.GenerateKeyValuePairByReadKey(keyType, key);
/*
reader.ReadColon()
*/
methodCall[1] = (Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon));
/*
value = ResolveProvider<ValueType>.InvokeGet(reader, handler);
*/
methodCall[2] = (Expression.Assign(value, ExpressionMembers.GetMethodCall(valueType)));
/*
iDic.Add(key,value);
*/
methodCall[3] = (Expression.Call(iDic, iDicAdd, key, value));
/*
if(reader.ReadComma()==true)
moveNext++;
*/
methodCall[4] = (ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement);
return Expression.Block(methodCall); ;
})
, Expression.Break(loopBreak)));
methodDictionaryCall[5] = Expression.Block(loopExpression, Expression.Label(loopBreak));
/*
reader.ReadObjRight();
*/
methodDictionaryCall[6] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight);
/*
return dictionary
*/
GotoExpression returnExpression = Expression.Return(returnTarget, dictionary);
LabelExpression returnLabel = Expression.Label(returnTarget, dictionary);
methodDictionaryCall[7] = returnExpression;
methodDictionaryCall[8] = returnLabel;
return Expression.Block(new[] { iDic, dictionary, key, value, ExpressionMembers.MoveNext }, methodDictionaryCall);
}
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.Dynamic)]
internal class DynamicBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type)
{
List<Expression> methodCall = new List<Expression>();
LabelTarget returnValueLable = Expression.Label(type, "returnValue");
var c = type.GetProperties();
ParameterExpression[] ctorArgs = null;
if (c.Length > 0)
{
ctorArgs = new ParameterExpression[c.Length];
for (int i = 0; i < c.Length; i++)
{
ctorArgs[i] = Expression.Variable(c[i].PropertyType);
if (c[i].PropertyType.IsValueType)
methodCall.Add(Expression.Assign(ctorArgs[i], Expression.New(c[i].PropertyType)));
else
methodCall.Add(Expression.Assign(ctorArgs[i], Expression.Constant(null, c[i].PropertyType)));
}
}
methodCall.Add(Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrObjLeft), Expression.Return(returnValueLable, Expression.Constant(null, type))));
methodCall.Add(Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolObjRight), Expression.Return(returnValueLable, c.Length == 0 ? Expression.New(type) : Expression.New(type.GetConstructors()[0], ctorArgs))));
/*
read.ReadLeftOrNull()
return null
if(_ReadBoolObjRight)
reture new (default)
int a;
string b;
i=2
while(i-->0)
{
var s= readString;
ReadColon()
switch(s)
case(s=='Name')
b=readValue
case(s=='Age')
a=readValue
arrig=true
if(!arrig)
throw
if(comma())
i++;
}
readRight();
return new dynamicModel(a,b)
*/
List<ParameterExpression> args = new List<ParameterExpression>() { };
if (c.Length > 0)
{
ParameterExpression str = Expression.Variable(typeof(string), "str");
LabelTarget whileBreak = Expression.Label();
methodCall.Add(ExpressionMembers.MoveNextAssignOne);
LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement,
ReturnFunc<Expression>(() =>
{
Expression[] expressions = new Expression[5];
expressions[0] = Expression.Assign(str, Expression.Call(ExpressionMembers.Reader, JsonReader._ReadString));
expressions[1] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon);
expressions[2] = Expression.Switch(str,
ReturnFunc(() =>
{
SwitchCase[] switchCases = new SwitchCase[c.Length];
for (int i = 0; i < c.Length; i++)
{
switchCases[i] = Expression.SwitchCase(
Expression.Block(typeof(void),
Expression.Assign(ctorArgs[i], ExpressionMembers.GetMethodCall(c[i].PropertyType)),
ExpressionMembers.IsArriveAssignTrue
)
, Expression.Constant(c[i].Name, typeof(string)));
}
return switchCases;
})
);
expressions[3] = Expression.IfThen(Expression.Equal(ExpressionMembers.IsArrive, Expression.Constant(false, typeof(bool))), Expression.Throw(Expression.New(JsonDeserializationTypeResolutionException._JsonDeserializationTypeResolutionExceptionMsgCtor, Expression.Constant("An error occurred parsing the dynamically typed key. The key does not match", typeof(string)))));
expressions[4] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement;
return Expression.Block(expressions);
}),
Expression.Break(whileBreak)
));
methodCall.Add(loopExpression);
methodCall.Add(Expression.Label(whileBreak));
args.Add(str);
args.AddRange(ctorArgs);
}
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight));
methodCall.Add(Expression.Return(returnValueLable, c.Length == 0 ? Expression.New(type) : Expression.New(type.GetConstructors()[0], ctorArgs)));
methodCall.Add(Expression.Label(returnValueLable, Expression.Constant(null, type)));
args.Add(ExpressionMembers.IsArrive);
args.Add(ExpressionMembers.MoveNext);
return Expression.Block(args, methodCall);
}
}
}

View File

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
internal static class ExpressionMembers
{
// -charVariable
internal static readonly ParameterExpression CharVariable = Expression.Variable(typeof(char), "charVariable");
//- reader (FuncArgs)
internal static readonly ParameterExpression Reader =
Expression.Parameter(typeof(JsonReader), "reader");
//- reader.Remaining (FuncArgs.Member)
internal static readonly MemberExpression Remaining =
Expression.MakeMemberAccess(Reader, JsonReader._Remaining);
//- reader.GetChar() (FuncArgs.Func)
internal static readonly Expression GetChar = Expression.Call(Reader,JsonReader._GetChar);
//- jsonDeserializeHandler (FuncArgs)
internal static readonly ParameterExpression JsonDeserializeHandler =
Expression.Parameter(typeof(JsonDeserializeHandler), "jsonDeserializeHandler");
//- jsonDeserializeHandler.jsonDeserializeOption (FuncArgs.Member)
internal static readonly MemberExpression JsonDeserializeOption =
Expression.MakeMemberAccess(JsonDeserializeHandler, Json.JsonDeserializeHandler. _Option
);
//- jsonDeserializeHandler.jsonCharacterReadState
internal static readonly MemberExpression JsonCharacterReadState =
Expression.MakeMemberAccess(JsonDeserializeOption, Json.JsonDeserializeOption._JsonCharacterReadState);
//- jsonDeserializeOption.GlobalValueFormat
internal static readonly MemberExpression GlobalValueFormat =
Expression.MakeMemberAccess(JsonDeserializeOption, Json.JsonDeserializeOption._GlobalValueFormat);
//- jsonDeserializeOption.GlobalValueFormat!=null
internal static readonly BinaryExpression GlobalValueFormatNotEqualNull = Expression.NotEqual(GlobalValueFormat,
Expression.Constant(null, Json.JsonDeserializeOption._GlobalValueFormat.FieldType));
//- jsonDeserializeOption.GlobalKeyFormat
internal static readonly MemberExpression GlobalKeyFormat =
Expression.MakeMemberAccess(JsonDeserializeOption, Json.JsonDeserializeOption._GlobalKeyFormat);
//- jsonDeserializeOption.GlobalKeyFormat!=null
internal static readonly BinaryExpression GlobalKeyFormatNotEqualNull = Expression.NotEqual(GlobalKeyFormat,
Expression.Constant(null, Json.JsonDeserializeOption._GlobalKeyFormat.FieldType));
//- jsonDeserializeOption.GlobalKeyFormat==null
internal static readonly BinaryExpression GlobalKeyFormatEqualNull = Expression.Equal(GlobalKeyFormat,
Expression.Constant(null, Json.JsonDeserializeOption._GlobalKeyFormat.FieldType));
//- afterFormatKey
internal static readonly ParameterExpression AfterFormatKey =
Expression.Variable(typeof(string), "afterFormatKey");
//- moveNext (Func.LocalVariable)
internal static readonly ParameterExpression MoveNext = Expression.Variable(typeof(int), "moveNext");
//- moveNext=1 (Func.LocalVariable.)
internal static readonly BinaryExpression MoveNextAssignOne =
Expression.Assign(MoveNext, Expression.Constant(1));
//- moveNext-->0
internal static readonly BinaryExpression MoveNextDecrement =
Expression.GreaterThan(Expression.PostDecrementAssign(MoveNext), Expression.Constant(0));
//- if(ReadBoolComma()==true) moveNext++;
internal static readonly ConditionalExpression IfReadBoolCommaIsTrueSoMoveNextIncrement =
Expression.IfThen(
Expression.Equal(Expression.Call(Reader, JsonReader._ReadBoolComma),
Expression.Constant(true, typeof(bool))),
Expression.Assign(MoveNext, Expression.Increment(MoveNext)));
//- isArrive (Func.LocalVariable)
internal static readonly ParameterExpression IsArrive = Expression.Variable(typeof(bool), "isArrive");
//- isArrive=true
internal static readonly BinaryExpression IsArriveAssignTrue =
Expression.Assign(IsArrive, Expression.Constant(true));
//- isArrive=false
internal static readonly BinaryExpression IsArriveAssignFalse =
Expression.Assign(IsArrive, Expression.Constant(false));
//- currentIdx
internal static readonly ParameterExpression CurrentIdx = Expression.Variable(typeof(int), "currentIdx");
//- currentIdx= Length - reader.Remaining
internal static readonly BinaryExpression CurrentIdxAssignReming = Expression.Assign(CurrentIdx,
Expression.Subtract(Expression.MakeMemberAccess(Reader, JsonReader._Length), Remaining));
//- isValueFormat
internal static readonly ParameterExpression IsValueFormat = Expression.Variable(typeof(bool), "isValueFormat");
//- isValueFormat==true
internal static readonly BinaryExpression IsValueFormatEqualTrue =
Expression.Equal(IsValueFormat, Expression.Constant(true, typeof(bool)));
//- valueLength
internal static readonly ParameterExpression ValueLength = Expression.Variable(typeof(int), "valueLength");
//- valueLength=reader.Skipobj()
internal static readonly BinaryExpression ValueLengthAssignSkipObj = Expression.Assign(ValueLength,
Expression.Call(Reader, JsonReader._SkipObj, JsonDeserializeHandler));
//- reader.RemoveQuoteAndSubString(currentIdx,valueLength)
internal static readonly Expression JsonRemoveQuoteAndSubstring =
Expression.Call(Reader, JsonReader._RemoveQuoteAndSubString, CurrentIdx, ValueLength);
//- object formatResult = ValueFormat.ReadValueFormat( reader.Json.Substring(currentIdx,leng) ,out isValueFormat);
internal static readonly ParameterExpression FormatResult = Expression.Variable(typeof(object), "formatResult");
internal static Expression GetMethodCall(Type type)
{
var realType = typeof(ResolveProvider<>).MakeGenericType(type);
return Expression.Call(realType.GetMethod("InvokeGet", BindingFlags.NonPublic | BindingFlags.Static),
Reader, JsonDeserializeHandler);
}
internal static Expression GenerateKeyValuePairByReadKey(Type keyType, Expression keyPara)
{
List<Expression> lists = new List<Expression>();
/*
reader._ReadQuotes()
*/
if (keyType.IsPrimitive)
lists.Add(Expression.Call(Reader, JsonReader._ReadQuotes));
/*
key = ResolveProvider<KeyType>.InvokeGet(reader, handler);
*/
lists.Add(Expression.Assign(keyPara, GetMethodCall(keyType)));
/*
if(getChar()!='"')
throw new Ex
*/
if (keyType.IsPrimitive)
lists.Add(Expression.IfThen(Expression.NotEqual(GetChar, Expression.Constant('"', typeof(char))),
Expression.Throw(Expression.New(JsonWrongCharacterException._JsonWrongCharacterExceptionCtor, Reader)
)));
return Expression.Block(lists);
}
}
}

View File

@ -0,0 +1,503 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.KeyValueObject)]
internal class KeyValueObjectBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type)
{
List<Expression> methodCall = new List<Expression>();
LabelTarget returnValueLable = Expression.Label(type, "returnValue");
if (type.IsValueType)
{
/*
ReadObjLeft()
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjLeft));
}
else
{
/*
if(_ReadNullOrObjLeft)
return null;/return default(ValueType)
*/
Expression ifReadNullOrObjLeftReturnNull1 = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrObjLeft),
Expression.Return(returnValueLable, Expression.Constant(null, type)
));
methodCall.Add(ifReadNullOrObjLeftReturnNull1);
}
/*
Model m=new Model();
*/
NewExpression newCtor = null;
if (type.IsValueType)
{
List<Expression> ctorArgs = null;
var ctor = type.GetValueTypeCtor(ref ctorArgs);
if (ctor == null)
newCtor = Expression.New(type);
else
newCtor = Expression.New(ctor, ctorArgs);
}
else
{
if (type.IsInterface)
{
//newCtor = Expression.New((Type)typeof(InterfaceImplementation<>).MakeGenericType(type).GetField("Proxy").GetValue(null));
throw new NotSupportedException();
}
else
{
List<Expression> ctorArgs = null;
var ctor = type.GetClassCtor(ref ctorArgs);
newCtor = Expression.New(ctor, ctorArgs);
}
}
ParameterExpression newModel = Expression.Variable(type, "newModel");
methodCall.Add(Expression.Assign(newModel, newCtor));
/*
if(reader.ReadBoolObjRight)
return m;
*/
methodCall.Add(Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolObjRight), Expression.Return(returnValueLable, newModel)));
/*
int moveNext=2;
*/
methodCall.Add(ExpressionMembers.MoveNextAssignOne); //Add moveNext localVirbale
/*
if(jsonDeserializeOption.IsFirstUpper)
while(moveNext-->0)
{ }
else if(jsonDeserializeOption.IsFirstLower)
while(moveNext-->0)
{ }
else
while(moveNext-->0)
{ }
*/
var charTries = type.GetCharTries();
if (charTries.Childrens.Count > 0)
methodCall.Add(GenerateWhile(newModel, type, charTries));
/*
reader.ReadObjRight()
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight));
/*
return newModel;
*/
methodCall.Add(Expression.Return(returnValueLable, newModel));
methodCall.Add(Expression.Label(returnValueLable, newModel));
return Expression.Block(new[] { ExpressionMembers.AfterFormatKey, ExpressionMembers.CurrentIdx, ExpressionMembers.IsValueFormat, ExpressionMembers.ValueLength, ExpressionMembers.FormatResult, ExpressionMembers.CharVariable, ExpressionMembers.MoveNext, ExpressionMembers.IsArrive, newModel }, methodCall);
}
private static BlockExpression GenerateWhile(ParameterExpression newModel, Type type, CharTries charTries)
{
//(state):0==The initial state does not change1==Capital letters2==Initial lowercase
/*
char c;
while(moveNext-->0)
{
}
*/
ParameterExpression firstChar = Expression.Variable(typeof(char), "firstChar");
LabelTarget tailOfMethod = Expression.Label(typeof(void), "tailOfMethod");
LabelTarget whileBreak = Expression.Label();
LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement,
ReturnFunc<Expression>(() =>
{
Expression[] expressions = new Expression[6];
/*
isArrive=false;
*/
expressions[0] = ExpressionMembers.IsArriveAssignFalse;
/*
2019-11-10 16:55:31,Add two configuration options of IgnoreJsonKeys and IsIgnoreExtraKeysInJSON
*/
expressions[1] = GenerateIgnoreKeys(type, tailOfMethod);
/*
* if(handler.option.GlobalKeyFormat!=null)
GenerateGlobalKeyFormat()
else
ReadKey()
*/
expressions[2] = Expression.IfThenElse(
Expression.NotEqual(Expression.MakeMemberAccess(ExpressionMembers.JsonDeserializeOption, JsonDeserializeOption._GlobalKeyFormat), Expression.Constant(null, JsonDeserializeOption._GlobalKeyFormat.FieldType)),
GenerateGlobalKeyFormat(type, newModel, tailOfMethod),
GenerateKeyValueObjectReadKey(firstChar, charTries, newModel)
);
/*
if(!isArrive)
throw
*/
expressions[3] = Expression.IfThen(Expression.Equal(ExpressionMembers.IsArrive, Expression.Constant(false, typeof(bool))), Expression.Throw(Expression.New(JsonDeserializationTypeResolutionException._JsonDeserializationTypeResolutionExceptionCtor, ExpressionMembers.Reader, type.IsInterface ? (Expression)Expression.Constant(type, typeof(Type)) : Expression.Call(newModel, type.GetMethod("GetType")))));
/*
Label -> tailOfMethod:
*/
expressions[4] = Expression.Label(tailOfMethod);
/*
if(reader.ReadComma()==true)
moveNext++;
*/
expressions[5] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement;
return Expression.Block(expressions);
})
, Expression.Break(whileBreak)));
return Expression.Block(new[] { firstChar }, loopExpression, Expression.Label(whileBreak));
}
private static Expression GenerateIgnoreKeys(Type type, LabelTarget tailOfMethod)
{
#region
/*
if(jsonDeserializeHandler.Option.JsonCharacterReadState == JsonCharacterReadStateEnum.None && jsonDeserializeHandler.Option.GlobalKeyFormat == null)
{
string key = reader.ReadString();
if(IsIgnoreExtraKeysInJSON){
if(TypeKeysCache<T>.NotContains(key))
{
reader.ReadColon();
Reader.ReadObject();
goto tailOfMethod;
}
if(IgnoreJsonKeysHasValue)
{
if(IgnoreKey.Contains(key))
{
reader.ReadColon();
Reader.ReadObject();
goto tailOfMethod;
}
}
if(key!=null)
Rollback(key.Length+2);
}
*/
#endregion
ParameterExpression key = Expression.Variable(typeof(string), "key");
return Expression.IfThen(Expression.AndAlso(Expression.Equal(ExpressionMembers.JsonCharacterReadState, Expression.Constant(JsonCharacterReadStateEnum.None, typeof(JsonCharacterReadStateEnum))), ExpressionMembers.GlobalKeyFormatEqualNull),
Expression.Block(new[] { key },
//string key=reader.ReadString();
Expression.Assign(key, Expression.Call(ExpressionMembers.Reader, JsonReader._ReadString)),
//if(IsIgnoreExtraKeysInJSON)
IfIsIgnoreExtraKeysInJsonThenSkipObject(key, type, tailOfMethod),
//if(IgnoreJsonKeysHasValue)
IfIgnoreJsonKeysHasValueThenSkipObject(key, tailOfMethod),
//if(key!=null)
Expression.IfThen(Expression.NotEqual(key, Expression.Constant(null, typeof(string))),
//Rollback(key.Length+2);
Expression.Call(ExpressionMembers.Reader, JsonReader._Rollback, Expression.Add(Expression.Property(key, typeof(string).GetProperty("Length")), Expression.Constant(2, typeof(int))))
)
)
);
}
private static Expression IfIsIgnoreExtraKeysInJsonThenSkipObject(ParameterExpression key, Type type, LabelTarget tailOfMethod)
{
return Expression.IfThen(Expression.Equal(Expression.MakeMemberAccess(ExpressionMembers.JsonDeserializeOption, JsonDeserializeOption._IsIgnoreExtraKeysInJSON), Expression.Constant(true, typeof(bool))),
//if(TypeKeysCache<T>.NotContains(key))
Expression.IfThen(Expression.Equal(Expression.Call(TypeUtils.GetContainsMethodInfo(type), key), Expression.Constant(true, typeof(bool))),
/*
reader.ReadColon();
Reader.SkipObject();
goto tailOfMethod;
*/
ReadColonAndSkipObjectAndGotoTailOfMethod(tailOfMethod)
)
);
}
private static Expression IfIgnoreJsonKeysHasValueThenSkipObject(ParameterExpression key, LabelTarget tailOfMethod)
{
return Expression.IfThen(Expression.Equal(Expression.MakeMemberAccess(ExpressionMembers.JsonDeserializeOption, JsonDeserializeOption._IgnoreJsonKeysHasValue), Expression.Constant(true, typeof(bool))),
//if(IgnoreKey.Contains(key))
Expression.IfThen(Expression.Call(Expression.MakeMemberAccess(ExpressionMembers.JsonDeserializeOption, JsonDeserializeOption._IgnoreJsonKeys), JsonDeserializeOption._IgnoreJsonKeyContains, key),
/*
reader.ReadColon();
Reader.SkipObject();
goto tailOfMethod;
*/
ReadColonAndSkipObjectAndGotoTailOfMethod(tailOfMethod)
)
);
}
private static Expression ReadColonAndSkipObjectAndGotoTailOfMethod(LabelTarget tailOfMethod)
{
return Expression.Block(
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon),
Expression.Call(ExpressionMembers.Reader, JsonReader._SkipObj, ExpressionMembers.JsonDeserializeHandler),
Expression.Goto(tailOfMethod)
);
}
private static Expression GenerateGlobalKeyFormat(Type type, ParameterExpression newModel, LabelTarget tailOfMethod)
{
return Expression.Block(
/*
var afterFormatKey = handler.option.GlobalKeyFormat.Invoke(reader.ReadString(),type)
*/
Expression.Assign(ExpressionMembers.AfterFormatKey,
Expression.Call(ExpressionMembers.GlobalKeyFormat, JsonDeserializeOption._GlobalKeyFormatInvoke,
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadString), Expression.Constant(type, typeof(Type)))),
/*
if(IsIgnoreExtraKeysInJSON){
if(!modelKeys.Contains(afterFormatKey))
{
reader.ReadColon();
Reader.ReadObject();
goto zuihou;
}
if(IsOpenIgnoreKey)
if(IgnoreKey.Contains(key))
{
reader.ReadColon();
Reader.ReadObject();
goto zuihou;
}
*/
IfIsIgnoreExtraKeysInJsonThenSkipObject(ExpressionMembers.AfterFormatKey, type, tailOfMethod),
IfIgnoreJsonKeysHasValueThenSkipObject(ExpressionMembers.AfterFormatKey, tailOfMethod),
/*
reader.ReadColon()
*/
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon),
/*
Switch(afterFormatKey)
case 'Name':
ReadValue()....
*/
Expression.Switch(
typeof(void),
ExpressionMembers.AfterFormatKey,
null, null,
ReturnFunc(() =>
{
var members = type.GetModelMembers();
SwitchCase[] switchCases = new SwitchCase[members.Count];
for (int i = 0; i < members.Count; i++)
{
var item = members[i];
switchCases[i] = Expression.SwitchCase(GenerateKeyValueObjectReadValue(item.Value, newModel), Expression.Constant(item.Key));
}
return switchCases;
})
),
/*
isArrive=true;
*/
ExpressionMembers.IsArriveAssignTrue
);
}
private static Expression GenerateKeyValueObjectReadValue(MemberExtension member, ParameterExpression newModel)
{
if (!member.IsProperty || (member.IsProperty && member.PropertyInfo.CanWrite))
{
var valueFormatAttribute = member.MemberInfo.GetCustomAttribute<ValueFormatAttribute>() ?? member.MemberInfo.DeclaringType.GetCustomAttribute<ValueFormatAttribute>();
if (valueFormatAttribute != null)//part
{
return (GenerateValueFormatCode(Expression.Constant(valueFormatAttribute, typeof(ValueFormatAttribute)), ValueFormatAttribute._ReadValueFormat, new[] { ExpressionMembers.JsonRemoveQuoteAndSubstring, Expression.Constant(member.Type, typeof(Type)), ExpressionMembers.JsonDeserializeHandler, ExpressionMembers.IsValueFormat }, newModel, member));
}
else //global
{
/*
if( jsonDeserializeHandler.jsonDeserializeOption .globalValueFormat!=null)
{
}
else
model.N=ReadJson();
*/
return (Expression.IfThenElse(ExpressionMembers.GlobalValueFormatNotEqualNull, GenerateValueFormatCode(ExpressionMembers.GlobalValueFormat, JsonDeserializeOption._GlobalValueFormatInvoke, new[] { ExpressionMembers.JsonRemoveQuoteAndSubstring, Expression.Constant(member.Type, typeof(Type)), ExpressionMembers.JsonDeserializeHandler, ExpressionMembers.IsValueFormat }, newModel, member), Expression.Assign(Expression.MakeMemberAccess(newModel, member.MemberInfo), ExpressionMembers.GetMethodCall(member.Type))));
}
}
else
/* SkipObj(); */
return (Expression.Call(ExpressionMembers.Reader, JsonReader._SkipObj, ExpressionMembers.JsonDeserializeHandler));
}
private static BlockExpression GenerateValueFormatCode(Expression formatDeclareInstance, MethodInfo callFormat, Expression[] paras, ParameterExpression newModel, MemberExtension member)
{
Expression[] expressions = new Expression[6];
/*
reader.BeforAnnotation();
reader.RollBackChar()
*/
expressions[0] = Expression.Call(ExpressionMembers.Reader, JsonReader._BeforAnnotation);
expressions[1] = Expression.Call(ExpressionMembers.Reader, JsonReader._RollbackChar);
/*
currentIdx= Length - reader.Remaining
*/
expressions[2] = ExpressionMembers.CurrentIdxAssignReming;
/*
valueLength=reader.Skipobj()
*/
expressions[3] = (ExpressionMembers.ValueLengthAssignSkipObj);
/*
object formatResult = ValueFormat.ReadValueFormat( reader.Substring(currentIdx,valueLength) ,out isValueFormat);
*/
expressions[4] = (Expression.Assign(ExpressionMembers.FormatResult, Expression.Call(formatDeclareInstance, callFormat, paras)));
/*
if(isValueFormat==true)
model.N=(Convert)obj;
else
reader.Rollback(valueLength)
m.N=ReadJson();//string
*/
expressions[5] = (Expression.IfThenElse(ExpressionMembers.IsValueFormatEqualTrue, Expression.Assign(Expression.MakeMemberAccess(newModel, member.MemberInfo), Expression.Convert(ExpressionMembers.FormatResult, member.Type)), Expression.Block(Expression.Call(ExpressionMembers.Reader, JsonReader._Rollback, ExpressionMembers.ValueLength), Expression.Assign(Expression.MakeMemberAccess(newModel, member.MemberInfo), ExpressionMembers.GetMethodCall(member.Type)))));
return Expression.Block(expressions);
}
private static Expression GenerateKeyValueObjectReadKey(ParameterExpression firstChar, CharTries charTries, ParameterExpression newModel)
{
return
Expression.IfThenElse(
Expression.NotEqual(ExpressionMembers.JsonCharacterReadState, Expression.Constant(JsonCharacterReadStateEnum.IgnoreCase, typeof(JsonCharacterReadStateEnum))),
GenerateKeyValueObjectReadKeyWithInitial(firstChar, charTries, newModel),
GenerateKeyValueObjectReadKeyWithIgnoreCase(charTries, newModel));
}
private static Expression GenerateKeyValueObjectReadKeyWithInitial(ParameterExpression firstChar, CharTries charTries, ParameterExpression newModel)
{
return Expression.Block(
/*
_ReadQuotes();
*/
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadQuotes),
/*
switch (handler.Option.InitialReadState)
{
case InitialReadStateEnum.None:
firstChar = reader.GetChar();
break;
case InitialReadStateEnum.Upper:
firstChar = char.ToUpper(reader.GetChar());
break;
case InitialReadStateEnum.Lower:
firstChar = char.ToLower(reader.GetChar());
break;
}
*/
Expression.Switch(typeof(void), ExpressionMembers.JsonCharacterReadState,
null, null,
Expression.SwitchCase(Expression.Assign(firstChar, ExpressionMembers.GetChar), Expression.Constant(JsonCharacterReadStateEnum.None, typeof(JsonCharacterReadStateEnum))),
Expression.SwitchCase(Expression.Assign(firstChar, Expression.Call(typeof(char).GetMethod("ToUpper", new[] { typeof(char) }), ExpressionMembers.GetChar)), Expression.Constant(JsonCharacterReadStateEnum.InitialUpper, typeof(JsonCharacterReadStateEnum))),
Expression.SwitchCase(Expression.Assign(firstChar, Expression.Call(typeof(char).GetMethod("ToLower", new[] { typeof(char) }), ExpressionMembers.GetChar)), Expression.Constant(JsonCharacterReadStateEnum.InitialLower, typeof(JsonCharacterReadStateEnum)))
),
/*
Switch(firstChar)
case 'N'
Switch(getChar())
case 'a'
Switch(getChar())
case 'm'
Switch(getChar())
case 'e'
Switch(getChar())
case '"':
ReadValue()...
*/
GenerateSwitchCodeByChar(firstChar, charTries, newModel)
);
}
private static Expression GenerateKeyValueObjectReadKeyWithIgnoreCase(CharTries charTries, ParameterExpression newModel)
{
return Expression.Block(
/*
_ReadQuotes();
*/
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadQuotes),
/*
Switch(getChar())
case 'N'
Switch(getChar())
case 'a'
Switch(getChar())
case 'm'
Switch(getChar())
case 'e'
Switch(getChar())
case '"':
ReadValue()...
*/
GenerateSwitchCodeByChar(null, charTries, newModel, true)
);
}
private static SwitchExpression GenerateSwitchCodeByChar(ParameterExpression firstChar, CharTries charTries, ParameterExpression newModel, bool isToLower = false)
{
List<SwitchCase> switchCases = new List<SwitchCase>();
if (charTries.IsValue)
{
//case '"'
var caseQuotes = Expression.SwitchCase(
Expression.Block(
typeof(void),
/*
ReadColon();
*/
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon),
GenerateKeyValueObjectReadValue(charTries.Member, newModel),
/*
isArrive=true;
*/
ExpressionMembers.IsArriveAssignTrue
)
, Expression.Constant('"', typeof(char)));
switchCases.Add(caseQuotes);
}
if (charTries.Childrens.Count > 0)
{
foreach (var item in charTries.Childrens)
{
char c = item.Val;
SwitchCase caseOrdinary = Expression.SwitchCase( //When there are two duplicate case items, the expression takes the first one automatically
GenerateSwitchCodeByChar(null, item, newModel, isToLower),
Expression.Constant(isToLower ? char.ToLower(c) : c, typeof(char)));
switchCases.Add(caseOrdinary);
}
}
return Expression.Switch(isToLower ? Expression.Call(typeof(char).GetMethod("ToLower", new[] { typeof(char) }), ExpressionMembers.GetChar) : firstChar ?? ExpressionMembers.GetChar, switchCases.ToArray());
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.KeyValuePair)]
internal class KeyValuePairBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type)
{
Type keyType = type.GetGenericArguments()[0];
Type valueType = type.GetGenericArguments()[1];
List<Expression> methodCall = new List<Expression>();
Type keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType);
LabelTarget returnValueLable = Expression.Label(keyValuePairType, "returnValue");
ConstructorInfo ctor = keyValuePairType.GetConstructor(new[] { keyType, valueType });
ParameterExpression key = Expression.Variable(keyType, "key");
ParameterExpression value = Expression.Variable(valueType, "value");
/*
ReadObjLeft()
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjLeft));
/*
if(reader.ReadBoolObjRight)
return new KeyValuePair<,>(default,default);
*/
methodCall.Add(
Expression.IfThen(
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolObjRight),
Expression.Return(returnValueLable, Expression.New(ctor, keyType.IsValueType ? (Expression)Expression.New(keyType) : Expression.Constant(null, keyType), valueType.IsValueType ? (Expression)Expression.New(valueType) : Expression.Constant(null, valueType)))));
/*
ReadKey()
*/
methodCall.Add(ExpressionMembers.GenerateKeyValuePairByReadKey(keyType, key));
/*
reader.ReadColon()
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon));
/*
value = ResolveProvider<ValueType>.InvokeGet(reader, handler);
*/
methodCall.Add(Expression.Assign(value, ExpressionMembers.GetMethodCall(valueType)));
/*
reader.ReadObjRight();
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight));
/*
return new KeyValuePair<,>(key,value);
*/
methodCall.Add(Expression.Return(returnValueLable, Expression.New(ctor, key, value)));
methodCall.Add(Expression.Label(returnValueLable, Expression.New(ctor, key, value)));
return Expression.Block(new[] { key, value }, methodCall);
}
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.Lazy)]
internal class LazyBuild : ExpressionJsonResolve
{
#region pregenerated metas
static MethodInfo _TransitionFunc = typeof(LazyBuild).GetMethod(nameof(TransitionFunc), BindingFlags.Static | BindingFlags.NonPublic);
#endregion
internal static BlockExpression Build(Type type)
{
LabelTarget returnTarget = Expression.Label(type, "returnLable");
Type elementType = type.GetGenericArguments()[0];
ParameterExpression element = Expression.Variable(elementType, "element");
var ctr = type.GetAppointTypeCtor(typeof(Func<>).MakeGenericType(elementType));
return Expression.Block(new[] { element },
Expression.IfThenElse(
Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolNull),
Expression.Return(returnTarget, Expression.Constant(null, type)),
Expression.Block(
Expression.Assign(element, ExpressionMembers.GetMethodCall(elementType)), //inject = Read<T>(); T-->)
Expression.Return(returnTarget, Expression.New(ctr, Expression.Call(_TransitionFunc.MakeGenericMethod(elementType), element)))
)),
Expression.Label(returnTarget, Expression.Constant(null, type))
);
}
private static Func<T> TransitionFunc<T>(T t)
{
return () => t;
}
}
}

View File

@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.MultiArray)]
internal class MultiArrayBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type multiType, Type sawtoothType, int rank)
{
LabelTarget returnValueLable = Expression.Label(multiType, "returnValue");
List<ParameterExpression> lambdaVariables = new List<ParameterExpression>();
Expression[] exs = new Expression[3];
ParameterExpression sawtoothAry = Expression.Variable(sawtoothType);
lambdaVariables.Add(sawtoothAry);
/*
int[][][] sawtoothAry= InvokeGet<int[][][]>();
*/
exs[0] = Expression.Assign(sawtoothAry, ExpressionMembers.GetMethodCall(sawtoothType));
/*
if(sawtoothAry==null)
return null;
else
...
*/
exs[1] = Expression.IfThenElse(
Expression.Equal(sawtoothAry, Expression.Constant(null, sawtoothType)),
Expression.Return(returnValueLable, Expression.Constant(null, multiType)),
ReturnFunc<Expression>(() =>
{
List<Expression> expressions = new List<Expression>();
/*
var index0_Length = sawtoothAry.Length;
var index1_Length = sawtoothAry[0].Length;
var index2_Length = sawtoothAry[0][0].Length;
var a = 0;
var b = 0;
var c = 0;
*/
ParameterExpression[] arrayLengthVariables = new ParameterExpression[rank];
ParameterExpression[] forVariables = new ParameterExpression[rank];
for (int i = 0; i < arrayLengthVariables.Length; i++)
{
arrayLengthVariables[i] = Expression.Variable(typeof(int));
expressions.Add(Expression.Assign(arrayLengthVariables[i], Expression.MakeMemberAccess(GetIndexAccessBySawtoothAry(sawtoothAry, GetExpressionConstantZero(i).ToArray()), typeof(Array).GetProperty("Length"))));
forVariables[i] = Expression.Variable(typeof(int));
}
lambdaVariables.AddRange(arrayLengthVariables);
/*
int[,,] multiAry=new multiAry(index0_Length,index1_Length,index2_Length)
*/
ParameterExpression multiAry = Expression.Variable(multiType);
lambdaVariables.Add(multiAry);
expressions.Add(Expression.Assign(multiAry, Expression.New(multiType.GetConstructors()[0], arrayLengthVariables)));
/*
for (int a = 0; a < index0_Length; a++)
{
for (int b = 0; b < index1_Length; b++)
{
for (int c = 0; c < index2_Length; c++)
{
multiAry[a,b,c] = sawtoothAry[a][b][c];
}
}
}
*/
Expression forMain = null;
for (int i = arrayLengthVariables.Length - 1; i >= 0; i--)
{
Expression content = null;
if (forMain == null)
{
/*
sawtoothAry[a][b][c];
*/
Expression sawtoothAryAccess = GetIndexAccessBySawtoothAry(sawtoothAry, forVariables);
/*
multiAry[a,b,c] = sawtoothAry[a][b][c];
*/
content = Expression.Assign(Expression.ArrayAccess(multiAry, forVariables), sawtoothAryAccess);
}
else
content = forMain;
forMain = ExpressionHelper.For(forVariables[i], Expression.LessThan(forVariables[i], arrayLengthVariables[i]), Expression.PostIncrementAssign(forVariables[i]),
content
);
}
expressions.Add(forMain);
/*
return multiAry
*/
expressions.Add(Expression.Return(returnValueLable, multiAry));
return Expression.Block(expressions);
}));
exs[2] = Expression.Label(returnValueLable, Expression.Constant(null, multiType));
return Expression.Block(lambdaVariables.ToArray(), exs);
}
internal static IEnumerable<Expression> GetExpressionConstantZero(int num)
{
for (int i = 0; i < num; i++)
{
yield return Expression.Constant(0);
}
}
internal static Expression GetIndexAccessBySawtoothAry(ParameterExpression sawtoothAry, Expression[] indexs)
{
if (!indexs.Any())
return sawtoothAry;
Expression lastAccess = null;
foreach (var t in indexs)
{
lastAccess = Expression.ArrayAccess(lastAccess ?? sawtoothAry, t);
}
return lastAccess;
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Deserialize
{
[ExpressionBuildType(DeserializeBuildTypeEnum.WrongGenericKey)]
internal class WrongGenericKeyBuild : ExpressionJsonResolve
{
internal static BlockExpression Build(Type type)
{
List<Expression> methodCall = new List<Expression>();
LabelTarget returnValueLable = Expression.Label(type, "returnValue");
/*
if(_ReadNullOrObjLeft)
return null;/return default(ValueType)
*/
Expression ifReadNullOrObjLeftReturnNull1 = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrObjLeft),
Expression.Return(returnValueLable, Expression.Constant(null, type)
));
methodCall.Add(ifReadNullOrObjLeftReturnNull1);
/*
reader.ReadObjRight()
*/
methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight));
/*
return new dictionary<,>;
*/
methodCall.Add(Expression.Return(returnValueLable, Expression.New(type)));
methodCall.Add(Expression.Label(returnValueLable, Expression.New(type)));
return Expression.Block(methodCall);
}
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace CPF.Json.Deserialize
{
internal class ExpressionJsonResolve : JsonResolveBase
{
internal static T ReturnFunc<T>(Func<T> f) => f();
}
}

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace CPF.Json
{
/// <summary>
/// Json Array
/// </summary>
public class JArray : List<object>
{
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace CPF.Json
{
/// <summary>
/// Json Object
/// </summary>
public class JObject : Dictionary<string, object>
{
public object this[int index] { get { return base[index.ToString()]; }set { base[index.ToString()] = value; } }
public object this[long index] { get { return base[index.ToString()]; } set { base[index.ToString()] = value; } }
public object this[Guid index] { get { return base[index.ToString()]; } set { base[index.ToString()] = value; } }
public object this[DateTime index] { get { return base[index.ToString()]; } set { base[index.ToString()] = value; } }
public object this[float index] { get { return base[index.ToString()]; } set { base[index.ToString()] = value; } }
public object this[double index] { get { return base[index.ToString()]; } set { base[index.ToString()] = value; } }
}
}

View File

@ -0,0 +1,765 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace CPF.Json.Deserialize
{
internal unsafe class JsonReader
{
#region pregenerated metas
internal static FieldInfo _Json =
typeof(JsonReader).GetField(nameof(Json), BindingFlags.NonPublic | BindingFlags.Instance);
internal static FieldInfo _Buffer =
typeof(JsonReader).GetField(nameof(Buffer), BindingFlags.NonPublic | BindingFlags.Instance);
internal static FieldInfo _Length =
typeof(JsonReader).GetField(nameof(Length), BindingFlags.NonPublic | BindingFlags.Instance);
internal static FieldInfo _Remaining =
typeof(JsonReader).GetField(nameof(Remaining), BindingFlags.NonPublic | BindingFlags.Instance);
internal static MethodInfo _RollbackChar = GetMethodInfo(nameof(RollbackChar));
internal static MethodInfo _Rollback = GetMethodInfo(nameof(Rollback));
internal static MethodInfo _ReadObjLeft = GetMethodInfo(nameof(ReadObjLeft));
internal static MethodInfo _ReadNullOrObjLeft = GetMethodInfo(nameof(ReadNullOrObjLeft));
internal static MethodInfo _ReadObjRight = GetMethodInfo(nameof(ReadObjRight));
internal static MethodInfo _ReadBoolObjRight = GetMethodInfo(nameof(ReadBoolObjRight));
internal static MethodInfo _ReadBoolComma = GetMethodInfo(nameof(ReadBoolComma));
internal static MethodInfo _ReadComma = GetMethodInfo(nameof(ReadComma));
internal static MethodInfo _ReadColon = GetMethodInfo(nameof(ReadColon));
internal static MethodInfo _ReadQuotes = GetMethodInfo(nameof(ReadQuotes));
internal static MethodInfo _ReadArrayLeft = GetMethodInfo(nameof(ReadArrayLeft));
internal static MethodInfo _ReadNullOrArrayLeft = GetMethodInfo(nameof(ReadNullOrArrayLeft));
internal static MethodInfo _ReadArrayRight = GetMethodInfo(nameof(ReadArrayRight));
internal static MethodInfo _ReadBoolArrayRight = GetMethodInfo(nameof(ReadBoolArrayRight));
internal static MethodInfo _ReadEnd = GetMethodInfo(nameof(ReadEnd));
internal static MethodInfo _BeforAnnotation = GetMethodInfo(nameof(BeforAnnotation));
internal static MethodInfo _ReadAnnotation = GetMethodInfo(nameof(ReadAnnotation));
internal static MethodInfo _ReadString = GetMethodInfo(nameof(ReadString));
internal static MethodInfo _ReadBoolNull = GetMethodInfo(nameof(ReadBoolNull));
internal static MethodInfo _SkipObj = GetMethodInfo(nameof(SkipObj));
internal static MethodInfo _GetArrayLength = GetMethodInfo(nameof(GetArrayLength));
internal static MethodInfo _RemoveQuoteAndSubString = GetMethodInfo(nameof(RemoveQuoteAndSubString));
internal static MethodInfo _GetChar = GetMethodInfo(nameof(GetChar));
#endregion
internal StringBuilder CharBufferSb;
internal string Json;
internal char[] Buffer;
internal int Length;
internal char* Pointer;
internal int Remaining;
internal JsonReader(string json, char* c)
{
Json = json;
Length = json.Length;
Pointer = c;
Remaining = Length;
CharBufferSb = null;
Buffer = null;
}
internal JsonReader(char[] buffer,int length, char* c)
{
Buffer = buffer;
Length = length;
Pointer = c;
Remaining = Length;
CharBufferSb = null;
Json = null;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal string SubString(int start, int length)
{
if (Json != null)
return Json.Substring(start, length);
else//char[]
return new string(Buffer, start, length);
}
internal char this[int idx]
{
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
get
{
if (Json != null)
return Json[idx];
else
return Buffer[idx];
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal char GetChar()
{
var c = *Pointer;
Pointer++;
Remaining--;
return c;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal int GetInt()
{
var i = *(int*)Pointer;
Pointer += 2;
Remaining -= 2;
return i;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal long GetLong()
{
var i = *(long*)Pointer;
Pointer += 4;
Remaining -= 4;
return i;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void RollbackChar()
{
Pointer--;
Remaining++;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void RollbackInt()
{
Pointer -= 2;
Remaining += 2;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void Rollback(int num)
{
Pointer -= num;
Remaining += num;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadObjLeft()
{
var c = BeforAnnotation();
if (c != '{')
throw new JsonWrongCharacterException(this, '{');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadNullOrObjLeft()
{
var c = BeforAnnotation();
if (c == 'n' && StrCompair("ull"))
return true;
if (c == '{')
return false;
throw new JsonWrongCharacterException(this, '{');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadObjRight()
{
var c = BeforAnnotation();
if (c != '}')
throw new JsonWrongCharacterException(this, '}');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadBoolObjRight()
{
var c = BeforAnnotation();
if (c == '}') return true;
RollbackChar();
return false;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadBoolComma()
{
var c = BeforAnnotation();
if (c == ',') return true;
RollbackChar();
return false;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadComma()
{
var c = BeforAnnotation();
if (c != ',')
throw new JsonWrongCharacterException(this, ',');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadColon()
{
var c = BeforAnnotation();
if (c != ':')
throw new JsonWrongCharacterException(this, ':');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadQuotes()
{
var c = BeforAnnotation();
if (c != '"')
throw new JsonWrongCharacterException(this, '"');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadArrayLeft()
{
var c = BeforAnnotation();
if (c != '[')
throw new JsonWrongCharacterException(this, '[');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadNullOrArrayLeft()
{
var c = BeforAnnotation();
if (c == 'n' && StrCompair("ull"))
return true;
if (c == '[')
return false;
throw new JsonWrongCharacterException(this, '[');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadArrayRight()
{
var c = BeforAnnotation();
if (c != ']')
throw new JsonWrongCharacterException(this, ']');
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadBoolArrayRight()
{
var c = BeforAnnotation();
if (c == ']') return true;
RollbackChar();
return false;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool ReadBoolNull()
{
var c = BeforAnnotation();
if (c == 'n' && StrCompair("ull"))
return true;
else
{
RollbackChar();
return false;
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadEnd()
{
if (Remaining > 0)
ReadAnnotation();
else if (Remaining < 0)
throw new JsonWrongCharacterException();
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal char BeforAnnotation()
{
var c = GetChar();
switch (c)
{
case '/':
{
if (Remaining == 0)
throw new JsonWrongCharacterException();
c = GetChar();
if (c == '*')
{
var lastChar = ' ';
while (Remaining > 0)
{
lastChar = c;
c = GetChar();
if (c == '/') // /* * */ /* ***/////
if (lastChar == '*')
{
if (Remaining > 0)
{
c = GetChar();
if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
return BeforAnnotation();
return c;
}
throw new JsonWrongCharacterException("Json is incomplete"); //json不完整
}
}
}
else if (c == '/')
{
while (Remaining > 0)
{
c = GetChar();
if (c == '\r' || c == '\n')
{
if (Remaining > 0)
{
c = GetChar();
if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
return BeforAnnotation();
return c;
}
throw new JsonWrongCharacterException("Json is incomplete"); //json不完整
}
}
}
throw new JsonWrongCharacterException();
}
case '\r':
case '\n':
case '\t':
case ' ':
if (Remaining > 0)
return BeforAnnotation();
else
throw new JsonWrongCharacterException("Json is incomplete"); //json不完整
}
return c;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void ReadAnnotation()
{
var c = GetChar();
switch (c)
{
case '/':
{
if (Remaining == 0)
throw new JsonWrongCharacterException();
c = GetChar();
if (c == '*')
{
var lastChar = ' ';
while (Remaining > 0)
{
lastChar = c;
c = GetChar();
if (c == '/') // /* * */ /* ***/////
if (lastChar == '*')
{
if (Remaining > 0)
ReadAnnotation();
return;
}
}
}
else if (c == '/')
{
while (Remaining > 0)
{
c = GetChar();
if (c == '\r' || c == '\n')
{
if (Remaining > 0)
ReadAnnotation();
return;
}
}
return;
}
break;
}
case '\r':
case '\n':
case '\t':
case ' ':
if (Remaining > 0)
ReadAnnotation();
return;
}
throw new JsonWrongCharacterException();
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal string ReadString()
{
//Currently, this method is only used for dynamic read keys and enums because it does not allow special characters
var c = BeforAnnotation();
if (c == '"')
{
var idx = Length - Remaining;
var leng = 0;
var isCorrectFormat = false;
while (Remaining > 0)
{
c = GetChar();
if (c == '"')
{
isCorrectFormat = true;
break;
}
leng++;
}
if (isCorrectFormat)
if (leng == 0)
return string.Empty;
else
return this.SubString(idx, leng);
}
else if (c == 'n' && StrCompair("ull"))
{
return null;
}
throw new JsonDeserializationTypeResolutionException(this, typeof(string));
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal int SkipObj(JsonDeserializeHandler handler)
{
var c = BeforAnnotation();
var start = Remaining;
switch (c)
{
case 'f':
if (Remaining > 3)
if (StrCompair("alse"))
goto Return;
break;
case 't':
if (Remaining > 2)
if (StrCompair("rue"))
goto Return;
break;
case 'n':
if (Remaining > 2)
if (StrCompair("ull"))
goto Return;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
{
SkipNumber();
goto Return;
}
case '[':
{
if (ReadBoolArrayRight())
goto Return;
var moveNext = 1;
while (moveNext-- > 0)
{
SkipObj(handler);
if (ReadBoolComma())
moveNext++;
}
ReadArrayRight();
goto Return;
}
case '{':
{
if (ReadBoolObjRight())
goto Return;
var moveNext = 1;
while (moveNext-- > 0)
{
SkipString();
ReadColon();
SkipObj(handler);
if (ReadBoolComma())
moveNext++;
}
ReadObjRight();
goto Return;
}
case '"':
{
RollbackChar();
SkipString();
goto Return;
}
}
throw new JsonWrongCharacterException(this);
Return:
return start + 1 - Remaining;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void SkipString()
{
var c = BeforAnnotation();
if (c == '"')
while (Remaining > 0)
{
c = GetChar();
if (c == '"')
return;
if (c != '\\')
continue;
c = GetChar();
switch (c)
{
case '"': continue;
case '\\': continue;
case '/': continue;
case 'b': continue;
case 'f': continue;
case 'n': continue;
case 'r': continue;
case 't': continue;
case 'u':
{
c = GetChar();
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) throw new JsonDeserializationTypeResolutionException(this, typeof(string));
c = GetChar();
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) throw new JsonDeserializationTypeResolutionException(this, typeof(string));
c = GetChar();
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) throw new JsonDeserializationTypeResolutionException(this, typeof(string));
c = GetChar();
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) throw new JsonDeserializationTypeResolutionException(this, typeof(string));
continue;
}
}
}
else if (c == 'n' && StrCompair("ull")) return;
throw new JsonDeserializationTypeResolutionException(this, typeof(string));
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal void SkipNumber()
{
var seenDecimal = false;
var seenExponent = false;
char c;
while (Remaining > 0)
{
c = GetChar();
if (c >= '0' && c <= '9') continue;
if (c == '.' && !seenDecimal)
{
seenDecimal = true;
continue;
}
if ((c == 'e' || c == 'E') && !seenExponent)
{
c = GetChar();
seenExponent = true;
seenDecimal = true;
c = GetChar();
if (c == '-' || c == '+' || c >= '0' && c <= '9') continue;
throw new JsonWrongCharacterException(this, "Expected -, or a digit");
}
RollbackChar();
return;
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal int GetArrayLength(JsonDeserializeHandler handler)
{
//ReadObjLeft();
if (ReadBoolArrayRight())
{
RollbackChar();
return 0;
}
var start = Remaining;
var elements = 0;
var moveNext = 1;
while (moveNext-- > 0)
{
++elements;
SkipObj(handler);
if (ReadBoolComma())
moveNext++;
}
ReadArrayRight();
Rollback(start - Remaining);
return elements;
throw new JsonWrongCharacterException("Array character error");
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal bool StrCompair(string str)
{
if (Remaining < str.Length)
return false;
//2,3,4,5,6,7,8,9
fixed (char* p = str)
{
var o = p;
switch (str.Length)
{
case 2:
if (*(int*)Pointer != *(int*)o) return false;
goto True;
case 3:
if (*(int*)Pointer != *(int*)o) return false;
if (*(Pointer + 2) != *(o + 2)) return false;
goto True;
case 4:
if (*(long*)Pointer != *(long*)o) return false;
goto True;
case 5:
if (*(long*)Pointer != *(long*)o) return false;
if (*(Pointer + 4) != *(o + 4)) return false;
goto True;
case 6:
if (*(long*)Pointer != *(long*)o) return false;
if (*(int*)(Pointer + 4) != *(int*)(o + 4)) return false;
goto True;
case 7:
if (*(long*)Pointer != *(long*)o) return false;
if (*(int*)(Pointer + 4) != *(int*)(o + 4)) return false;
if (*(Pointer + 6) != *(o + 6)) return false;
goto True;
case 8:
if (*(long*)Pointer != *(long*)o) return false;
if (*(long*)(Pointer + 4) != *(long*)(o + 4)) return false;
goto True;
case 9:
if (*(long*)Pointer != *(long*)o) return false;
if (*(long*)(Pointer + 4) != *(long*)(o + 4)) return false;
if (*(Pointer + 8) != *(o + 8)) return false;
goto True;
default:
throw new Exception("Check the code,StrCompair no current length ");
}
}
True:
Remaining -= str.Length;
Pointer += str.Length;
return true;
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal string RemoveQuoteAndSubString(int idx, int length)
{
if (this[idx] == 'n')
return null;
return this.SubString(idx + 1, length - 2); //remove \" \"
}
private static MethodInfo GetMethodInfo(string name)
{
return typeof(JsonReader).GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance);
}
}
}

View File

@ -0,0 +1,6 @@
namespace CPF.Json.Deserialize
{
internal class JsonResolveBase
{
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace CPF.Json
{
/// <summary>
/// 对Model进行Json反序列化时全局值格式化器
/// Global value formatter for Json deserialization of Model
/// </summary>
/// <param name="jsonFragment">Json字符串中的片段,Fragments in the Json string</param>
/// <param name="elementType">该jsonFragment所对应的类型,The type corresponding to the jsonFragment</param>
/// <param name="jsonDeserializeHandler">提供一些选项进行访问,Provides options for access</param>
/// <param name="isValueFormat">决定最终是否进行值格式化,Determines whether the value is ultimately formatted</param>
/// <returns></returns>
public delegate object JsonDeserializeGlobalValueFormatDelegate(string jsonFragment, Type elementType, JsonDeserializeHandler jsonDeserializeHandler, out bool isValueFormat);
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace CPF.Json
{
/// <summary>
/// Json Deserialize Handler
/// </summary>
public class JsonDeserializeHandler
{
#region pregenerated metas
internal static FieldInfo _Types =
typeof(JsonDeserializeHandler).GetField(nameof(Types), BindingFlags.NonPublic | BindingFlags.Instance);
internal static FieldInfo _Option =
typeof(JsonDeserializeHandler).GetField(nameof(Option), BindingFlags.Instance | BindingFlags.Public);
#endregion
/// <summary>
/// Json Serializer Option
/// </summary>
public JsonDeserializeOption Option = null;
internal Queue<Type> Types = new Queue<Type>();
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace CPF.Json
{
/// <summary>
/// 反序列化全局配置项
/// Deserialized global configuration's options
/// </summary>
public class JsonDeserializeOption
{
#region pregenerated metas
internal static readonly FieldInfo _JsonCharacterReadState = typeof(JsonDeserializeOption).GetField(nameof(JsonCharacterReadState));
internal static readonly MethodInfo _GlobalKeyFormatInvoke = typeof(Func<string, Type, string>).GetMethod("Invoke");
internal static readonly FieldInfo _GlobalKeyFormat = typeof(JsonDeserializeOption).GetField(nameof(GlobalKeyFormat));
internal static readonly MethodInfo _GlobalValueFormatInvoke = typeof(JsonDeserializeGlobalValueFormatDelegate).GetMethod("Invoke");
internal static readonly FieldInfo _GlobalValueFormat = typeof(JsonDeserializeOption).GetField(nameof(GlobalValueFormat));
internal static readonly FieldInfo _IgnoreJsonKeys = typeof(JsonDeserializeOption).GetField(nameof(IgnoreJsonKeys));
internal static readonly FieldInfo _IsIgnoreExtraKeysInJSON = typeof(JsonDeserializeOption).GetField(nameof(IsIgnoreExtraKeysInJSON));
internal static readonly PropertyInfo _IgnoreJsonKeysHasValue = typeof(JsonDeserializeOption).GetProperty(nameof(IgnoreJsonKeysHasValue), BindingFlags.NonPublic | BindingFlags.Instance);
internal static readonly MethodInfo _IgnoreJsonKeyContains = typeof(HashSet<string>).GetMethod("Contains");
#endregion
/// <summary>
/// 对Model的全局Key格式化器
/// Read the first letter of Key in Model: default, capitalization, lowercase
/// </summary>
public Func<string, Type, string> GlobalKeyFormat;
/// <summary>
/// 对Model的全局Value格式化器
/// Global Value Formatter for Model
/// </summary>
public JsonDeserializeGlobalValueFormatDelegate GlobalValueFormat;
/// <summary>
/// 对Model中的字符读取状态默认、首字母大写、首字母小写、忽略大小写
/// Read status for characters in the Model: Default, Initial uppercase, Initial lowercase, Ignore case
/// </summary>
public JsonCharacterReadStateEnum JsonCharacterReadState = JsonCharacterReadStateEnum.None;
/// <summary>
/// 在对Model进行反序列化时,当JsonCharacterReadState为默认值时,忽略JSON字符中指定的Key
/// When deserializing a model, the key specified in the JSON character is ignored when the JsonCharacterReadState is the default
/// </summary>
public HashSet<string> IgnoreJsonKeys;
/// <summary>
/// 在对Model进行反序列化时,当JsonCharacterReadState为默认值时,是否忽略JSON字符中多余的Key
/// When deserializing the model, whether to ignore the extra key in the JSON character when JsonCharacterReadState is the default value
/// </summary>
public bool IsIgnoreExtraKeysInJSON;
internal bool IgnoreJsonKeysHasValue => IgnoreJsonKeys != null && IgnoreJsonKeys.Count > 0;
}
}

View File

@ -0,0 +1,459 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Deserialize
{
internal class ResolveFind<T>
{
internal static ResolveDelegate<T> Find()
{
Type t = typeof(T);
return FindTypeIsDefaultImplemented(t) ?? FindTypeIsMeetDefaultCondition(t) ?? FindTypeIsDefaultImplementedBaseType(t) ?? FindTypeIsDefaultImplementedInterface(t) ?? DefaultResolve(t);
}
private static ResolveDelegate<T> FindTypeIsDefaultImplemented(Type t)
{
if (DeserializeBootTable.Table.DefaultSameTypes.TryGetValue(t, out var member))
return GenerateLambdaCall(member);
return null;
}
private static ResolveDelegate<T> FindTypeIsMeetDefaultCondition(Type t)
{
return IsArray(t) ?? IsEnum(t) ?? IsDynamic(t);
}
private static ResolveDelegate<T> FindTypeIsDefaultImplementedBaseType(Type t)
{
var baseTypes = t.GetTypeAndBaseTypes();
//Avoid
if (DeserializeBootTable.Table.DefaultAvoidTypes.Intersect(baseTypes).Any())
return GenerateLambdaCall(SpecialConditionsResolve._ReadAvoidNull);
//BaseType
foreach (var item in DeserializeBootTable.Table.DefaultImplementedBaseType)
{
var implementedType = item.Key;
foreach (var baseType in baseTypes)
{
if (baseType == implementedType)
{
return GenerateLambdaCall(item.Value.MethodInfo);
}
}
}
return null;
}
private static ResolveDelegate<T> FindTypeIsDefaultImplementedInterface(Type t)
{
var intserfaces = t.GetInterfaces().ToList();
if (t.IsInterface)
intserfaces.Add(t);
foreach (var item in DeserializeBootTable.Table.DefaultImplementedInterfaces)
{
var implementedInterfaces = item.Key;
foreach (var objInterface in intserfaces)
{
if (objInterface == implementedInterfaces)
{
return GenerateLambdaCall(item.Value.MethodInfo);
}
}
}
return null;
}
private static ResolveDelegate<T> DefaultResolve(Type t)
{
Func<ResolveDelegate<T>> func = TypeIsDictionary(t) ?? TypeIsCollection(t) ?? TypeIsSpecial(t);
if (func != null)
return func();
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.KeyValueObject, t);
}
private static Func<ResolveDelegate<T>> TypeIsCollection(Type t)
{
return TypeIsCollectionInterface(t) ?? TypeIsCollectionType(t);
}
private static Func<ResolveDelegate<T>> TypeIsDictionary(Type t)
{
return TypeIsDictionaryInterface(t) ?? TypeIsDictionaryType(t);
}
private static Func<ResolveDelegate<T>> TypeIsSpecial(Type t)
{
if (t.IsGenericType)
{
var genericTypeDefinition = t.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(Nullable<>))
return () => GenerateLambdaCall(SpecialConditionsResolve._ReadNullable.MakeGenericMethod(t.GetGenericArguments()[0]));
else if (genericTypeDefinition == typeof(Lazy<>))
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Lazy, t);
}
else if (genericTypeDefinition == typeof(Lookup<,>))
{
}
else if (genericTypeDefinition == typeof(KeyValuePair<,>))
{
var keyType = t.GetGenericArguments()[0];
var func = IsWrongKeyType(keyType);
if (func != null)
return () => func;
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.KeyValuePair, t);
}
else if (genericTypeDefinition == typeof(ILookup<,>))
{
}
}
return null;
}
private static Func<ResolveDelegate<T>> TypeIsCollectionInterface(Type t)
{
if (t == typeof(IEnumerable) || t == typeof(ICollection) || t == typeof(IList))
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, typeof(List<object>), typeof(List<object>), typeof(object));
if (t.IsGenericType)
{
var genericTypeDefinition = t.GetGenericTypeDefinition();
var arrayItemType = t.GetGenericArguments()[0];
if (genericTypeDefinition == typeof(IEnumerable<>) || genericTypeDefinition == typeof(IList<>) || genericTypeDefinition == typeof(ICollection<>))
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, typeof(List<>).MakeGenericType(arrayItemType), typeof(List<>).MakeGenericType(arrayItemType), arrayItemType);
#if !Net4
if (genericTypeDefinition == typeof(IReadOnlyList<>) || genericTypeDefinition == typeof(IReadOnlyCollection<>))
{
var ctor = typeof(ReadOnlyCollection<>).MakeGenericType(arrayItemType).GetCtorByParameterInterfaceType(typeof(IList<>).MakeGenericType(arrayItemType));
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(ReadOnlyCollection<>).MakeGenericType(arrayItemType), ctor);
}
#endif
if (genericTypeDefinition == typeof(ISet<>))
{
var ctor = typeof(HashSet<>).MakeGenericType(arrayItemType).GetCtorByParameterInterfaceType(typeof(IEnumerable<>).MakeGenericType(arrayItemType));
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(HashSet<>).MakeGenericType(arrayItemType), ctor);
}
}
return null;
}
private static Func<ResolveDelegate<T>> TypeIsDictionaryInterface(Type t)
{
if (t == typeof(IDictionary))
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, typeof(Dictionary<string, object>), typeof(Dictionary<string, object>), typeof(string), typeof(object));
if (t.IsGenericType)
{
Type[] args = t.GetGenericArguments();
if (args.Length != 2)
return null;
var genericTypeDefinition = t.GetGenericTypeDefinition();
var keyType = args[0];
var valueType = args[1];
if (genericTypeDefinition == typeof(IDictionary<,>))
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, typeof(Dictionary<,>).MakeGenericType(keyType, valueType), t, keyType, valueType);
#if !Net4
if (genericTypeDefinition == typeof(IReadOnlyDictionary<,>))
{
var ctor = typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType).GetCtorByParameterInterfaceType(typeof(IDictionary<,>).MakeGenericType(keyType, valueType));
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType), ctor);
}
#endif
}
return null;
}
private static Func<ResolveDelegate<T>> TypeIsCollectionType(Type t)
{
if (t.IsInterface)
return null;
var intserfaces = t.GetInterfaces();
bool hasIEnumerableGeneric = false;
bool hasICollectionGeneric = false;
bool hasICollection = false;
bool hasIList = false;
Type arrayItemType = null;
Type iCollectionGenericType = null;
Type iEnumerableGenericType = null;
foreach (var item in intserfaces)
{
if (item.IsGenericType)
{
var genericTypeDefinition = item.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IEnumerable<>))
{
hasIEnumerableGeneric = true;
arrayItemType = item.GetGenericArguments()[0];
iEnumerableGenericType = item;
}
else if (genericTypeDefinition == typeof(ICollection<>))
{
hasICollectionGeneric = true;
arrayItemType = item.GetGenericArguments()[0];
iCollectionGenericType = item;
}
}
else if (item == typeof(ICollection))
hasICollection = true;
else if (item == typeof(IList))
hasIList = true;
}
if (hasICollectionGeneric)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iCollectionGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else if (ctor.GetParameters().Length == 0) //如果空的构造函数则调用接口Add方法
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, t, iCollectionGenericType, arrayItemType);
}
else //如果构造函数为iCollectionGenericType则注入iCollectionGenericType
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, iCollectionGenericType, ctor);
}
if (hasIEnumerableGeneric && hasICollection)
{
var ctor = t.GetAppointTypeCtor(iEnumerableGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, iEnumerableGenericType, ctor);
}
if (hasIList)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IList));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else if (ctor.GetParameters().Length == 0) //如果空的构造函数则调用接口Add方法
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, t, typeof(IList), typeof(object));
}
else //如果构造函数为iCollectionGenericType则注入iCollectionGenericType
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(IList), ctor);
}
if (hasICollection)
{
var ctor = t.GetAppointTypeCtor(typeof(ICollection));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(ICollection), ctor);
}
return null;
}
private static Func<ResolveDelegate<T>> TypeIsDictionaryType(Type t)
{
if (t.IsInterface)
return null;
var intserfaces = t.GetInterfaces();
bool hasIDictionaryGeneric = false;
bool hasIDictionary = false;
Type iDictionaryGenericType = null;
Type keyType = null;
Type valueType = null;
foreach (var item in intserfaces)
{
if (item.IsGenericType)
{
var genericTypeDefinition = item.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IDictionary<,>))
{
iDictionaryGenericType = item;
hasIDictionaryGeneric = true;
keyType = item.GetGenericArguments()[0];
valueType = item.GetGenericArguments()[1];
}
}
if (item == typeof(IDictionary))
hasIDictionary = true;
}
if (hasIDictionaryGeneric)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iDictionaryGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (TypeIsDictionary(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => IsWrongKeyType(keyType) ?? BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, t, iDictionaryGenericType, keyType, valueType);
}
else
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, iDictionaryGenericType, ctor);
}
if (hasIDictionary)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IDictionary));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (TypeIsDictionary(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, t, typeof(IDictionary), typeof(string), typeof(object));
}
else
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(IDictionary), ctor);
}
return null;
}
private static ResolveDelegate<T> IsArray(Type t)
{
if (t.IsArray)
{
int rank = t.GetArrayRank();
if (rank == 1)
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.Array, t);
else
{
Type sawtoothType = t.GetElementType();
int i = rank;
while (i-- > 0)
{
var obj = Array.CreateInstance(sawtoothType, 0);
sawtoothType = obj.GetType();
}
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.MultiArray, t, sawtoothType, rank);
}
}
return null;
}
private static ResolveDelegate<T> IsEnum(Type t)
{
if (t.IsEnum)
return GenerateLambdaCallWithEnqueueType(SpecialConditionsResolve._ReadEnum, t);
return null;
}
private static ResolveDelegate<T> IsDynamic(Type t)
{
if (t.IsAnonymousType())
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dynamic, t);
return null;
}
private static ResolveDelegate<T> IsWrongKeyType(Type keyType)
{
if (keyType.IsWrongKey())
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.WrongGenericKey);
return null;
}
private static ResolveDelegate<T> GenerateLambdaCall(MethodInfo methodInfo)
{
ParameterExpression readerArg = Expression.Parameter(typeof(JsonReader), "reader");
ParameterExpression handlerArg = Expression.Parameter(typeof(JsonDeserializeHandler), "handler");
var body = Expression.Call(methodInfo, readerArg, handlerArg);
return Expression.Lambda<ResolveDelegate<T>>(body, readerArg, handlerArg).Compile();
}
private static ResolveDelegate<T> GenerateLambdaCallWithEnqueueType(MethodInfo methodInfo, Type t)
{
ParameterExpression readerArg = Expression.Parameter(typeof(JsonReader), "reader");
ParameterExpression handlerArg = Expression.Parameter(typeof(JsonDeserializeHandler), "handler");
MemberExpression option = Expression.MakeMemberAccess(handlerArg, JsonDeserializeHandler._Types);
LabelTarget label = Expression.Label(t);
var body = Expression.Block(Expression.Call(option, typeof(Queue<Type>).GetMethod("Enqueue"), Expression.Constant(t, typeof(Type)))
, Expression.Return(label, Expression.Convert(Expression.Call(methodInfo, readerArg, handlerArg), t)),
Expression.Label(label, Expression.Convert(Expression.Call(methodInfo, readerArg, handlerArg), t))
);
return Expression.Lambda<ResolveDelegate<T>>(body, readerArg, handlerArg).Compile();
}
}
}

View File

@ -0,0 +1,48 @@
using System.IO;
using System.Runtime.CompilerServices;
namespace CPF.Json.Deserialize
{
internal class ResolveProvider<T>
{
internal static ResolveDelegate<T> Get = ResolveFind<T>.Find();
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static unsafe T Convert(string json, JsonDeserializeHandler handler)
{
fixed (char* c = json)
{
JsonReader reader = new JsonReader(json, c);
T result = Get(reader, handler);
reader.ReadEnd();
return result;
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static unsafe T Convert(StreamReader streamReader, JsonDeserializeHandler handler)
{
//peek() => call ReadBuffer(); =>call internal origin stream byte[] copy local byte[] -> default utf8 convert -> generate char[]
streamReader.Peek();
char[] buf = StreamOperate.GetStreamReaderCharBuffer(streamReader);
int len = StreamOperate.GetStreamReaderCharLen(streamReader);
fixed (char* c = buf)
{
JsonReader reader = new JsonReader(buf,len, c);
T result = Get(reader, handler);
reader.ReadEnd();
return result;
}
}
internal static T InvokeGet(JsonReader reader, JsonDeserializeHandler jsonDeserializeHandler)
{
return Get(reader, jsonDeserializeHandler);
}
}
internal delegate T ResolveDelegate<T>(JsonReader jsonReader, JsonDeserializeHandler handler);
}

View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace CPF.Json
{
internal class BootTable
{
internal Dictionary<Type, MethodInfo> DefaultSameTypes = new Dictionary<Type, MethodInfo>();
internal List<KeyValuePair<Type, MethodInfoOrder>> DefaultImplementedInterfaces = new List<KeyValuePair<Type, MethodInfoOrder>>();
internal List<KeyValuePair<Type, MethodInfoOrder>> DefaultImplementedBaseType = new List<KeyValuePair<Type, MethodInfoOrder>>();
internal HashSet<Type> DefaultAvoidTypes;
internal List<Type> ExpressionBuildTypes = new List<Type>();
public BootTable(BootTableTypeEnum bootTableTypeEnum)
{
Type normalBaseType = null;
Type expressBaseTypes = null;
switch (bootTableTypeEnum)
{
case BootTableTypeEnum.DeserializeResolve:
normalBaseType = typeof(Deserialize.DefaultJsonResolve);
expressBaseTypes = typeof(Deserialize.ExpressionJsonResolve);
break;
case BootTableTypeEnum.SerializerLogic:
normalBaseType = typeof(Serializer.DefaultJsonFormatter);
expressBaseTypes = typeof(Serializer.ExpressionJsonFormatter);
break;
}
var normalMethods = new List<MethodInfo>();
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
if (type.BaseType == expressBaseTypes)
ExpressionBuildTypes.Add(type);
if (type.BaseType == normalBaseType)
normalMethods.AddRange(type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic));
}
foreach (var item in normalMethods)
{
var atr = item.GetCustomAttribute<FuncLableAttribute>();
if (atr == null)
continue;
Type t = null;
switch (bootTableTypeEnum)
{
case BootTableTypeEnum.DeserializeResolve:
t = item.ReturnType;
break;
case BootTableTypeEnum.SerializerLogic:
t = item.GetParameters()[0].ParameterType;
break;
}
switch (atr._Type)
{
case FuncType.SameType:
DefaultSameTypes.Add(t, item);
break;
case FuncType.BaseType:
DefaultImplementedBaseType.Add(new KeyValuePair<Type, MethodInfoOrder>(t, new MethodInfoOrder(item, atr._Priority)));
break;
case FuncType.Interface:
DefaultImplementedInterfaces.Add(new KeyValuePair<Type, MethodInfoOrder>(t, new MethodInfoOrder(item, atr._Priority)));
break;
}
}
DefaultImplementedBaseType = DefaultImplementedBaseType.OrderBy(e => e.Value.Priority).ToList();
DefaultImplementedInterfaces = DefaultImplementedInterfaces.OrderBy(e => e.Value.Priority).ToList();
DefaultAvoidTypes = new HashSet<Type>() {
typeof(Process),
typeof(Delegate),
typeof(Thread),
typeof(Task)
};
}
}
}

View File

@ -0,0 +1,8 @@
namespace CPF.Json
{
internal enum BootTableTypeEnum
{
SerializerLogic,
DeserializeResolve
}
}

View File

@ -0,0 +1,22 @@
using System.Runtime.CompilerServices;
namespace CPF.Json
{
internal static class CharHelper
{
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static int CharToNumber(this char x)
{
if ('0' <= x && x <= '9')
return x - '0';
if ('a' <= x && x <= 'f')
return x - 'a' + 10;
if ('A' <= x && x <= 'F')
return x - 'A' + 10;
throw new JsonWrongCharacterException("The code unit format is incorrect");
}
}
}

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
namespace CPF.Json.Deserialize
{
internal class CharTries
{
internal char Val;
internal MemberExtension Member;
internal bool IsPeak;
internal bool IsValue;
internal CharTries Parent;
internal List<CharTries> Childrens;
internal CharTries() {
Childrens = new List<CharTries>();
IsValue = false;
}
internal void Insert(string str,MemberExtension mem)
{
CharTries charTries = this;
foreach (var c in str)
{
var @case = charTries.Childrens.Find(e => e.Val == c);
if (@case == null)
{
@case = new CharTries() { Val = c, Parent=charTries };
charTries.Childrens.Add(@case);
}
charTries = @case;
}
charTries.IsValue = true;
charTries.Member = mem;
}
}
}

View File

@ -0,0 +1,7 @@
namespace CPF.Json.Deserialize
{
internal static class DeserializeBootTable
{
internal static BootTable Table = new BootTable(BootTableTypeEnum.DeserializeResolve);
}
}

View File

@ -0,0 +1,78 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Text;
namespace CPF.Json
{
internal class ExpressionHelper
{
internal static Expression For(ParameterExpression loopVar, Expression condition, Expression increment, Expression loopContent)
{
var initAssign = Expression.Assign(loopVar, Expression.Constant(0));
var breakLabel = Expression.Label("LoopBreak");
var loop = Expression.Block(new[] { loopVar },
initAssign,
Expression.Loop(
Expression.IfThenElse(
condition,
Expression.Block(
loopContent,
increment
),
Expression.Break(breakLabel)
),
breakLabel)
);
return loop;
}
internal static Expression ForEach(Expression enumerable, ParameterExpression loopVar, Func<ParameterExpression, Expression> loopContentAc)
{
var elementType = loopVar.Type;
var enumerableType = typeof(IEnumerable<>).MakeGenericType(elementType);
var enumeratorType = typeof(IEnumerator<>).MakeGenericType(elementType);
var enumeratorVar = Expression.Variable(enumeratorType, "enumerator");
var getEnumeratorCall = Expression.Call(enumerable, enumerableType.GetMethod("GetEnumerator"));
var enumeratorAssign = Expression.Assign(enumeratorVar, getEnumeratorCall);
var enumeratorDispose = Expression.Call(enumeratorVar, typeof(IDisposable).GetMethod("Dispose"));
// The MoveNext method's actually on IEnumerator, not IEnumerator<T>
var moveNextCall = Expression.Call(enumeratorVar, typeof(IEnumerator).GetMethod("MoveNext"));
var breakLabel = Expression.Label("LoopBreak");
var trueConstant = Expression.Constant(true);
var loop =
Expression.Loop(
Expression.IfThenElse(
Expression.Equal(moveNextCall, trueConstant),
Expression.Block(
new[] { loopVar },
Expression.Assign(loopVar, Expression.Property(enumeratorVar, "Current")),
loopContentAc(loopVar)),
Expression.Break(breakLabel)),
breakLabel);
var tryFinally =
Expression.TryFinally(
loop,
enumeratorDispose);
var body =
Expression.Block(
new[] { enumeratorVar },
enumeratorAssign,
tryFinally);
return body;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using CPF.Json.Deserialize;
using CPF.Json.Serializer;
namespace CPF.Json
{
internal class ExpressionBuildTypeAttribute : Attribute
{
internal DeserializeBuildTypeEnum _deserializeBuildType;
internal SerializerBuildTypeEnum _serializerBuildTypeEnum;
internal ExpressionBuildTypeAttribute(DeserializeBuildTypeEnum buildType)
{
_deserializeBuildType = buildType;
}
internal ExpressionBuildTypeAttribute(SerializerBuildTypeEnum buildType)
{
_serializerBuildTypeEnum = buildType;
}
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace CPF.Json
{
[AttributeUsage(AttributeTargets.Method)]
internal class FuncLableAttribute : Attribute
{
public FuncType _Type;
public int _Priority;
public FuncLableAttribute(FuncType funcType)
{
_Type = funcType;
}
public FuncLableAttribute(FuncType funcType, int priority)
{
_Type = funcType;
_Priority = priority;
}
}
}

View File

@ -0,0 +1,9 @@
namespace CPF.Json
{
internal enum FuncType
{
SameType,
BaseType,
Interface
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Json
{
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct GuidStruct
{
[FieldOffset(0)]
internal Guid Value;
[FieldOffset(0)]
public byte B00;
[FieldOffset(1)]
public byte B01;
[FieldOffset(2)]
public byte B02;
[FieldOffset(3)]
public byte B03;
[FieldOffset(4)]
public byte B04;
[FieldOffset(5)]
public byte B05;
[FieldOffset(6)]
public byte B06;
[FieldOffset(7)]
public byte B07;
[FieldOffset(8)]
public byte B08;
[FieldOffset(9)]
public byte B09;
[FieldOffset(10)]
public byte B10;
[FieldOffset(11)]
public byte B11;
[FieldOffset(12)]
public byte B12;
[FieldOffset(13)]
public byte B13;
[FieldOffset(14)]
public byte B14;
[FieldOffset(15)]
public byte B15;
public GuidStruct(Guid invisibleMembers)
: this()
{
Value = invisibleMembers;
}
}
}

View File

@ -0,0 +1,31 @@
namespace CPF.Json
{
/// <summary>
/// 对Model中的字符读取状态默认、首字母大写、首字母小写、忽略大小写
/// Read status for characters in the Model: Default, Initial uppercase, Initial lowercase, Ignore case
/// </summary>
public enum JsonCharacterReadStateEnum
{
/// <summary>
/// 默认
/// Default
/// </summary>
None,
/// <summary>
/// 首字母大写
/// Initial uppercase
/// </summary>
InitialUpper,
/// <summary>
/// 首字母小写
/// Initial lowercase
/// </summary>
InitialLower,
/// <summary>
/// 仅反序列化时使用,忽略大小写
/// Used only for deserialization ,Ignore case
/// </summary>
IgnoreCase
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Reflection;
namespace CPF.Json
{
internal class MemberExtension
{
internal Type Type { get; set; }
internal string Name { get; set; }
internal MemberInfo MemberInfo { get; set; }
internal FieldInfo FieldInfo { get; set; }
internal PropertyInfo PropertyInfo { get; set; }
internal bool IsProperty { get; set; }
internal int OrderNum { get; set; }
internal MemberExtension(PropertyInfo pro)
{
MemberInfo = pro;
PropertyInfo = pro;
Name = pro.Name;
IsProperty = true;
Type = pro.PropertyType;
}
internal MemberExtension(FieldInfo pro)
{
MemberInfo = pro;
FieldInfo = pro;
Name = pro.Name;
IsProperty = false;
Type = pro.FieldType;
}
}
}

View File

@ -0,0 +1,19 @@
using System.Reflection;
namespace CPF.Json
{
internal class MethodInfoOrder
{
internal MethodInfo MethodInfo;
internal int Priority;
public MethodInfoOrder(MethodInfo methodInfo)
{
MethodInfo = methodInfo;
}
public MethodInfoOrder(MethodInfo methodInfo,int priority)
{
MethodInfo = methodInfo;
Priority = priority;
}
}
}

View File

@ -0,0 +1,205 @@
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace CPF.Json.Serializer
{
internal class RemoveWriterHelper
{
internal static MethodInfo _RemoveDictionaryKey = typeof(RemoveWriterHelper).GetMethod(nameof(RemoveDictionaryKey), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(JsonSerializerHandler) }, null);
internal static void RemoveDictionaryKey(JsonSerializerHandler handler)
{
if (handler.stringBuilder != null)
{
if (handler.stringBuilder.Length < 3)
return;
int startIndex = 0;
int leng = -1;
for (int i = handler.stringBuilder.Length - 2 - 1; i >= 0; i--)
{
if (handler.stringBuilder[i] == '"')
{
startIndex = i;
leng = handler.stringBuilder.Length - i;
if (i - 1 > 0)
{
if (handler.stringBuilder[i - 1] == ',')
{
startIndex = startIndex - 1;
leng = leng + 1;
}
}
handler.stringBuilder.Remove(startIndex, leng);
return;
}
}
}
else
{
int length = StreamOperate.GetStreamWriterCharLen(handler.streamWriter);
if (length < 3)
return;
char[] buf = StreamOperate.GetStreamWriterCharBuffer(handler.streamWriter);
int startIndex = 0;
int leng = -1;
for (int i = length - 2 - 1; i >= 0; i--)
{
if (buf[i] == '"')
{
startIndex = i;
leng = length - i;
if (i - 1 > 0)
{
if (buf[i - 1] == ',')
{
startIndex = startIndex - 1;
leng = leng + 1;
}
}
handler.streamWriter.Remove(startIndex, leng);
return;
}
}
}
}
internal static MethodInfo _RemoveArrayItem = typeof(RemoveWriterHelper).GetMethod(nameof(RemoveArrayItem), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(JsonSerializerHandler) }, null);
internal static void RemoveArrayItem(JsonSerializerHandler handler)
{
if (handler.stringBuilder != null)
{
if (handler.stringBuilder.Length <= 1)
return;
if (handler.stringBuilder[handler.stringBuilder.Length - 1] == '[')
return;
if (handler.stringBuilder[handler.stringBuilder.Length - 1] == ':')
RemoveDictionaryKey(handler);
else
handler.stringBuilder.Remove(handler.stringBuilder.Length - 1, 1);
}
else
{
int length = StreamOperate.GetStreamWriterCharLen(handler.streamWriter);
if (length <= 1)
return;
char[] buf = StreamOperate.GetStreamWriterCharBuffer(handler.streamWriter);
if (buf[length - 1] == '[')
return;
if (buf[length - 1] == ':')
RemoveDictionaryKey(handler);
else
handler.streamWriter.Remove(length - 1, 1);
}
}
internal static MethodInfo _RemoveKeyAndAddIndex = typeof(RemoveWriterHelper).GetMethod(nameof(RemoveKeyAndAddIndex), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(JsonSerializerHandler), typeof(Stack<int>) }, null);
internal static void RemoveKeyAndAddIndex(JsonSerializerHandler handler, Stack<int> commaIndexs)
{
if (handler.stringBuilder != null)
{
StringBuilder sb = handler.stringBuilder;
if (sb.Length < 3)
return;
int startIndex = 0;
int leng = -1;
for (int i = sb.Length - 2 - 1; i >= 0; i--)
{
if (sb[i] == '"')
{
startIndex = i;
leng = sb.Length - i;
sb.Remove(startIndex, leng);
commaIndexs.Push(sb.Length - 1);
return;
}
}
}
else
{
int length = StreamOperate.GetStreamWriterCharLen(handler.streamWriter);
if (length < 3)
return;
int startIndex = 0;
char[] buf = StreamOperate.GetStreamWriterCharBuffer(handler.streamWriter);
int leng = -1;
for (int i = length - 2 - 1; i >= 0; i--)
{
if (buf[i] == '"')
{
startIndex = i;
leng = length - i;
handler.streamWriter.Remove(startIndex, leng);
commaIndexs.Push(length - leng - 1);
return;
}
}
}
}
internal static MethodInfo _RemoveLastComma = typeof(RemoveWriterHelper).GetMethod(nameof(RemoveLastComma), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(JsonSerializerHandler) }, null);
internal static void RemoveLastComma(JsonSerializerHandler handler)
{
if (handler.stringBuilder != null)
{
StringBuilder sb = handler.stringBuilder;
if (sb[sb.Length - 1] == ',')
sb.Remove(sb.Length - 1, 1);
}
else
{
int length = StreamOperate.GetStreamWriterCharLen(handler.streamWriter);
char[] buf = StreamOperate.GetStreamWriterCharBuffer(handler.streamWriter);
if (buf[length - 1] == ',')
handler.streamWriter.Remove(length - 1, 1);
}
}
internal static MethodInfo _DeleteComma = typeof(RemoveWriterHelper).GetMethod(nameof(DeleteComma), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(JsonSerializerHandler), typeof(Stack<int>) }, null);
internal static void DeleteComma(JsonSerializerHandler handler, Stack<int> lists)
{
if (handler.stringBuilder != null)
{
StringBuilder sb = handler.stringBuilder;
if (lists.Count > 0)
{
RemoveLastComma(handler);
var lastCommaIndex = lists.Peek();
if (lastCommaIndex >= sb.Length - 1)
{
lists.Pop();
}
}
while (lists.Count > 0)
{
var index = lists.Pop();
sb.Remove(index + 1, 1);
}
}
else
{
if (lists.Count > 0)
{
RemoveLastComma(handler);
var lastCommaIndex = lists.Peek();
if (lastCommaIndex >= StreamOperate.GetStreamWriterCharLen(handler.streamWriter) - 1)
{
lists.Pop();
}
}
while (lists.Count > 0)
{
var index = lists.Pop();
handler.streamWriter.Remove(index + 1, 1);
}
}
}
}
}

View File

@ -0,0 +1,7 @@
namespace CPF.Json.Serializer
{
internal static class SerializerBootTable
{
internal static BootTable Table = new BootTable(BootTableTypeEnum.SerializerLogic);
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Text;
namespace CPF.Json
{
internal static class StreamOperate
{
internal static Func<StreamReader, char[]> GetStreamReaderCharBuffer = BuildStreamReaderCharBufferFunc();
internal static Func<StreamReader, int> GetStreamReaderCharLen = BuildStreamReaderCharLenFunc();
static Func<StreamReader, char[]> BuildStreamReaderCharBufferFunc()
{
var instance = Expression.Parameter(typeof(StreamReader));
var info = typeof(StreamReader).GetField("_charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?? typeof(StreamReader).GetField("charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var buf = Expression.MakeMemberAccess(instance, info);
return Expression.Lambda<Func<StreamReader, char[]>>(buf, new[] { instance }).Compile();
}
static Func<StreamReader, int> BuildStreamReaderCharLenFunc()
{
var instance = Expression.Parameter(typeof(StreamReader));
var info = typeof(StreamReader).GetField("_charLen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?? typeof(StreamReader).GetField("charLen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var len = Expression.MakeMemberAccess(instance, info);
return Expression.Lambda<Func<StreamReader, int>>(len, new[] { instance }).Compile();
}
internal static Func<StreamWriter, char[]> GetStreamWriterCharBuffer = BuildStreamWriterCharBufferFunc();
internal static Func<StreamWriter, int> GetStreamWriterCharLen = BuildStreamWriterCharPosFunc();
internal static Action<StreamWriter, int> SetStreamWriterCharLen = BuildSetStreamWriterCharPosFunc();
static Func<StreamWriter, char[]> BuildStreamWriterCharBufferFunc()
{
var instance = Expression.Parameter(typeof(StreamWriter));
var info = typeof(StreamWriter).GetField("_charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?? typeof(StreamWriter).GetField("charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var buf = Expression.MakeMemberAccess(instance, info);
return Expression.Lambda<Func<StreamWriter, char[]>>(buf, new[] { instance }).Compile();
}
static Func<StreamWriter, int> BuildStreamWriterCharPosFunc()
{
var instance = Expression.Parameter(typeof(StreamWriter));
var info = typeof(StreamWriter).GetField("_charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?? typeof(StreamWriter).GetField("charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var pos = Expression.MakeMemberAccess(instance, info);
return Expression.Lambda<Func<StreamWriter, int>>(pos, new[] { instance }).Compile();
}
static Action<StreamWriter, int> BuildSetStreamWriterCharPosFunc()
{
var instance = Expression.Parameter(typeof(StreamWriter));
var num = Expression.Parameter(typeof(int));
var info = typeof(StreamWriter).GetField("_charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?? typeof(StreamWriter).GetField("charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var pos = Expression.MakeMemberAccess(instance, info);
var assign = Expression.Assign(pos, num);
return Expression.Lambda<Action<StreamWriter, int>>(assign, new[] { instance, num }).Compile();
}
internal unsafe static void Remove(this StreamWriter streamWriter, int start, int length)
{
int pos = GetStreamWriterCharLen(streamWriter);
SetStreamWriterCharLen(streamWriter, pos - length);
if (start + length == pos)
return;
char[] buf = GetStreamWriterCharBuffer(streamWriter);
Array.Copy(buf, start + length, buf, start, pos - (start + length));
}
}
}

View File

@ -0,0 +1,434 @@
using CPF.Json.Deserialize;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace CPF.Json
{
internal enum ReadMemberStateEnum
{
All,
CanRead,
CanWrite
}
internal static class TypeKeysCache<T>
{
internal static string[] Keys = typeof(T).GetModelMembers().Select(e => e.Key).ToArray();
internal static bool NotContains(string key) => !Keys.Contains(key);
}
internal static class TypeUtils
{
internal static MethodInfo GetContainsMethodInfo(Type t)
{
return typeof(TypeKeysCache<>).MakeGenericType(t).GetMethod("NotContains", BindingFlags.NonPublic | BindingFlags.Static);
}
internal static bool IsAnonymousType(this Type type)
{
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
internal static List<KeyValuePair<string, MemberExtension>> GetModelMembers(this Type type, ReadMemberStateEnum readMemberStateEnum = ReadMemberStateEnum.All)
{
List<KeyValuePair<string, MemberExtension>> list = new List<KeyValuePair<string, MemberExtension>>();
List<KeyValuePair<string, MemberExtension>> jsonOnlyIncludeLists = new List<KeyValuePair<string, MemberExtension>>();
Type ignoreAttribute = typeof(IgnoreKeyAttribute);
List<PropertyInfo> pors = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
if (type.IsInterface)
{
Type[] interfaces = type.GetInterfaces();
if (interfaces.Length > 0)
{
foreach (var item in interfaces)
{
pors.AddRange(item.GetProperties());
}
}
}
foreach (var item in pors)
{
if (item.IsDefined(ignoreAttribute, false))
continue;
if (item.GetIndexParameters().Length > 0)
continue;
if (readMemberStateEnum == ReadMemberStateEnum.CanRead)
{
if (!item.CanRead)
continue;
}
else if (readMemberStateEnum == ReadMemberStateEnum.CanWrite)
{
if (!item.CanWrite)
continue;
}
var mem = new MemberExtension(item);
//alias
AliasAttribute alias = item.GetCustomAttribute<AliasAttribute>(false);
var name = alias != null ? alias._name : mem.Name;
//order
JsonOrderAttribute order = item.GetCustomAttribute<JsonOrderAttribute>(false);
mem.OrderNum = order?._orderNum ?? ushort.MaxValue + 1;
//jsonOnlyIncludeAttribute
JsonOnlyIncludeAttribute jsonMember = item.GetCustomAttribute<JsonOnlyIncludeAttribute>(false);
if (jsonMember != null)
jsonOnlyIncludeLists.Add(new KeyValuePair<string, MemberExtension>(name, mem));
list.Add(new KeyValuePair<string, MemberExtension>(name, mem));
}
FieldInfo[] fils = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (var item in fils)
{
if (item.IsDefined(ignoreAttribute, false))
continue;
var mem = new MemberExtension(item);
//alias
AliasAttribute alias = item.GetCustomAttribute<AliasAttribute>(false);
var name = alias != null ? alias._name : mem.Name;
//order
JsonOrderAttribute order = item.GetCustomAttribute<JsonOrderAttribute>(false);
mem.OrderNum = order?._orderNum ?? ushort.MaxValue + 1;
//jsonOnlyIncludeAttribute
JsonOnlyIncludeAttribute jsonMember = item.GetCustomAttribute<JsonOnlyIncludeAttribute>(false);
if (jsonMember != null)
jsonOnlyIncludeLists.Add(new KeyValuePair<string, MemberExtension>(name, mem));
list.Add(new KeyValuePair<string, MemberExtension>(name, mem));
}
if (jsonOnlyIncludeLists.Count > 0)
{
jsonOnlyIncludeLists = jsonOnlyIncludeLists.OrderBy(e => e.Value.OrderNum).ToList();
return jsonOnlyIncludeLists;
}
list = list.OrderBy(e => e.Value.OrderNum).ToList();
return list;
}
internal static CharTries GetCharTries(this Type type)
{
CharTries charTries = new CharTries() { IsPeak = true };
type.GetModelMembers(ReadMemberStateEnum.All).ForEach(
e =>
charTries.Insert(e.Key, e.Value)
);
return charTries;
}
internal static List<Type> GetTypeAndBaseTypes(this Type type)
{
List<Type> types = new List<Type>();
if (type != null)
{
types.Add(type);
types.AddRange(GetBaseTypes(type));
}
return types;
}
internal static List<Type> GetBaseTypes(this Type type)
{
List<Type> types = new List<Type>();
if (type != null)
{
if (type.BaseType != null && type.BaseType != typeof(object))
{
types.Add(type.BaseType);
types.AddRange(GetBaseTypes(type.BaseType));
}
}
return types;
}
internal static List<MemberInfo> GetAllInterfaceMembers(this Type type)
{
if (!type.IsInterface) throw new Exception("Expected interface, found: " + type);
var pending = new Stack<Type>();
pending.Push(type);
var ret = new List<MemberInfo>();
while (pending.Count > 0)
{
var current = pending.Pop();
ret.AddRange(current.GetMembers());
if (current.BaseType != null)
{
pending.Push(current.BaseType);
}
foreach (var x in current.GetInterfaces())
{
pending.Push(x);
}
}
return ret;
}
internal static ConstructorInfo GetValueTypeCtor(this Type type, ref List<Expression> args)
{
var cs = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (var item in cs)
{
var pars = item.GetParameters();
JsonDeserializeCtorAttribute jsonDeserializeCtorAttribute = item.GetCustomAttribute<JsonDeserializeCtorAttribute>();
if (jsonDeserializeCtorAttribute != null)
{
args = new List<Expression>();
for (int i = 0; i < jsonDeserializeCtorAttribute._args.Length; i++)
{
args.Add(Expression.Constant(jsonDeserializeCtorAttribute._args[i], pars[i].ParameterType));
}
return item;
}
}
return null;
}
internal static ConstructorInfo GetClassCtor(this Type type, ref List<Expression> args)
{
var cs = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
ConstructorInfo attrCtor = null, publicNoArgsCtor = null, privateNoArgsCtor = null, publicArgsCtor = null, privateArgsCtor = null;
List<Expression> attrCtorArgs = null; ParameterInfo[] publicArgsCtorParas = null, privateArgsCtorParas = null;
foreach (var item in cs)
{
var pars = item.GetParameters();
JsonDeserializeCtorAttribute jsonDeserializeCtorAttribute = item.GetCustomAttribute<JsonDeserializeCtorAttribute>();
if (jsonDeserializeCtorAttribute != null)
{
attrCtorArgs = new List<Expression>();
attrCtor = item;
for (int i = 0; i < jsonDeserializeCtorAttribute._args.Length; i++)
{
attrCtorArgs.Add(Expression.Constant(jsonDeserializeCtorAttribute._args[i], pars[i].ParameterType));
}
break;
}
if (item.IsPublic)
{
if (pars.Length == 0)
{
publicNoArgsCtor = item;
}
else if (publicArgsCtor == null || pars.Length < publicArgsCtor.GetParameters().Length)
{
publicArgsCtor = item;
publicArgsCtorParas = pars;
}
}
else if (item.IsPrivate)
{
if (pars.Length == 0)
{
privateNoArgsCtor = item;
}
else if (privateArgsCtor == null || pars.Length < privateArgsCtor.GetParameters().Length)
{
privateArgsCtor = item;
privateArgsCtorParas = pars;
}
}
}
if (attrCtor != null)
{
args = attrCtorArgs;
return attrCtor;
}
if (publicNoArgsCtor != null)
{
args = null;
return publicNoArgsCtor;
}
if (privateNoArgsCtor != null)
{
args = null;
return privateNoArgsCtor;
}
if (publicArgsCtor != null)
{
args = new List<Expression>();
for (int i = 0; i < publicArgsCtorParas.Length; i++)
{
object value = null;
var paraType = publicArgsCtorParas[i].ParameterType;
if (paraType.IsValueType)
value = Activator.CreateInstance(paraType);
args.Add(Expression.Constant(value, paraType));
}
return publicArgsCtor;
}
else //(privateArgsCtor != null)
{
args = new List<Expression>();
for (int i = 0; i < publicArgsCtorParas.Length; i++)
{
object value = null;
var paraType = publicArgsCtorParas[i].ParameterType;
if (paraType.IsValueType)
value = Activator.CreateInstance(paraType);
args.Add(Expression.Constant(value, paraType));
}
return privateArgsCtor;
}
}
internal static ConstructorInfo GetCtorByParameterInterfaceType(this Type type, params Type[] ctorParaTypes)
{
foreach (var ctor in type.GetConstructors())
{
var ctorParas = ctor.GetParameters();
if (ctorParas.Length == ctorParaTypes.Length)
{
bool isTrue = true;
for (int i = 0; i < ctorParaTypes.Length; i++)
{
if (ctorParas[i].ParameterType != ctorParaTypes[i])
{
isTrue = false;
break;
}
}
if (isTrue)
return ctor;
}
}
return null;
}
internal static ConstructorInfo GetDefaultNoArgCtorOrAppointTypeCtor(this Type type, Type ctorParaTypes = null)
{
foreach (var ctor in type.GetConstructors())
{
var ctorParas = ctor.GetParameters();
if (ctorParas.Length == 0)
return ctor;//no args
if (ctorParaTypes != null && ctorParas.Length == 1)
{
if (ctorParas[0].ParameterType == ctorParaTypes)
return ctor;
}
}
return null;
}
internal static ConstructorInfo GetAppointTypeCtor(this Type type, Type ctorParaTypes)
{
foreach (var ctor in type.GetConstructors())
{
var ctorParas = ctor.GetParameters();
if (ctorParas.Length == 1 && ctorParas[0].ParameterType == ctorParaTypes)
{
return ctor;
}
}
return null;
}
internal static bool HasEmptyCtor(this Type type)
{
if (type.IsInterface)
return false;
foreach (var ctor in type.GetConstructors())
{
var ctorParas = ctor.GetParameters();
if (ctorParas.Length == 0)
return true;
}
return false;
}
internal static bool IsWrongKey(this Type keyType)
{
if (!keyType.IsPrimitive && !keyType.IsEnum && keyType != typeof(string) && keyType != typeof(Guid) && keyType != typeof(DateTime))
return true;
return false;
}
internal static object GetDefaultValue(this Type type)
{
if (type.IsValueType)
return Activator.CreateInstance(type);
return null;
}
#if Net4
public static Attribute GetCustomAttribute(this Assembly element, Type attributeType)
{
return Attribute.GetCustomAttribute(element, attributeType);
}
public static Attribute GetCustomAttribute(this Module element, Type attributeType)
{
return Attribute.GetCustomAttribute(element, attributeType);
}
public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType)
{
return Attribute.GetCustomAttribute(element, attributeType);
}
public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType)
{
return Attribute.GetCustomAttribute(element, attributeType);
}
public static T GetCustomAttribute<T>(this Assembly element) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T));
}
public static T GetCustomAttribute<T>(this Module element) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T));
}
public static T GetCustomAttribute<T>(this MemberInfo element) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T));
}
public static T GetCustomAttribute<T>(this ParameterInfo element) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T));
}
public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType, bool inherit)
{
return Attribute.GetCustomAttribute(element, attributeType, inherit);
}
public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType, bool inherit)
{
return Attribute.GetCustomAttribute(element, attributeType, inherit);
}
public static T GetCustomAttribute<T>(this MemberInfo element, bool inherit) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T), inherit);
}
public static T GetCustomAttribute<T>(this ParameterInfo element, bool inherit) where T : Attribute
{
return (T)GetCustomAttribute(element, typeof(T), inherit);
}
#endif
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Runtime.CompilerServices;
namespace CPF.Json.Serializer
{
internal class BaseTypeNormal: DefaultJsonFormatter
{
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.BaseType)]
internal static void WriteValue(Exception value, JsonSerializerHandler handler)
{
if (value == null)
handler.WriteString("null");
else
{
handler.WriteString("{\"Message\":");
PrimitiveNormal.WriteValue(value.Message, handler);
handler.WriteString(",\"Source\":");
PrimitiveNormal.WriteValue(value.Source, handler);
handler.WriteString(",\"StackTrace\":");
PrimitiveNormal.WriteValue(value.StackTrace, handler);
handler.WriteString(",\"HelpLink\":");
PrimitiveNormal.WriteValue(value.HelpLink, handler);
handler.WriteString("}");
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.BaseType)]
internal static void WriteValue(Type value, JsonSerializerHandler handler)
{
if (value == null)
handler.WriteString("null");
else
PrimitiveNormal.WriteValue(value.AssemblyQualifiedName, handler);
}
}
}

View File

@ -0,0 +1,400 @@
using System;
using System.Globalization;
using System.Runtime.CompilerServices;
namespace CPF.Json.Serializer
{
internal class PrimitiveNormal : DefaultJsonFormatter
{
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(int value, JsonSerializerHandler handler)
{
// Gotta special case this, we can't negate it
if (value == int.MinValue)
{
handler.WriteString("-2147483648");
return;
}
if (value == int.MaxValue)
{
handler.WriteString("2147483647");
return;
}
var ptr = 35;
char[] buffer = new char[36];
uint copy;
if (value < 0)
{
handler.WriteChar('-');
copy = (uint)(-value);
}
else
copy = (uint)value;
do
{
byte ix = (byte)(copy % 100);
copy /= 100;
var chars = SpecialTypeNormal. DigitPairs[ix];
buffer[ptr--] = chars.Second;
buffer[ptr--] = chars.First;
} while (copy != 0);
if (buffer[ptr + 1] == '0')
{
ptr++;
}
handler.WriteChars(buffer, ptr + 1, 35 - ptr);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(uint value, JsonSerializerHandler handler)
{
if (value == uint.MaxValue)
{
handler.WriteString("4294967295");
return;
}
var ptr = 35;
char[] buffer = new char[36];
var copy = value;
do
{
byte ix = (byte)(copy % 100);
copy /= 100;
var chars = SpecialTypeNormal.DigitPairs[ix];
buffer[ptr--] = chars.Second;
buffer[ptr--] = chars.First;
} while (copy != 0);
if (buffer[ptr + 1] == '0')
{
ptr++;
}
handler.WriteChars(buffer, ptr + 1, 35 - ptr);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(long value, JsonSerializerHandler handler)
{
if (value == long.MinValue)
{
handler.WriteString("-9223372036854775808");
return;
}
char[] buffer = new char[36];
var ptr = 35;
ulong copy;
if (value < 0)
{
handler.WriteChar('-');
copy = (ulong)(-value);
}
else
{
copy = (ulong)value;
}
do
{
byte ix = (byte)(copy % 100);
copy /= 100;
var chars = SpecialTypeNormal.DigitPairs[ix];
buffer[ptr--] = chars.Second;
buffer[ptr--] = chars.First;
} while (copy != 0);
if (buffer[ptr + 1] == '0')
{
ptr++;
}
handler.WriteChars(buffer, ptr + 1, 35 - ptr);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(ulong value, JsonSerializerHandler handler)
{
if (value == ulong.MaxValue)
{
handler.WriteString("18446744073709551615");
return;
}
var ptr = 35;
char[] buffer = new char[36];
var copy = value;
do
{
byte ix = (byte)(copy % 100);
copy /= 100;
var chars = SpecialTypeNormal.DigitPairs[ix];
buffer[ptr--] = chars.Second;
buffer[ptr--] = chars.First;
} while (copy != 0);
if (buffer[ptr + 1] == '0')
{
ptr++;
}
handler.WriteChars(buffer, ptr + 1, 35 - ptr);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(float value, JsonSerializerHandler handler)
{
switch (value)
{
case float.NaN:
handler.WriteString("\"NaN\"");
return;
case float.NegativeInfinity:
handler.WriteString("\"-Infinity\"");
return;
case float.PositiveInfinity:
handler.WriteString("\"Infinity\"");
return;
}
handler.WriteString(value.ToString("R",CultureInfo.InvariantCulture));
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(decimal value, JsonSerializerHandler handler)
{
handler.WriteString(value.ToString(CultureInfo.InvariantCulture));
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(double value, JsonSerializerHandler handler)
{
switch (value)
{
case double.NaN:
handler.WriteString("\"NaN\"");
return;
case double.NegativeInfinity:
handler.WriteString("\"-Infinity\"");
return;
case double.PositiveInfinity:
handler.WriteString("\"Infinity\"");
return;
}
handler.WriteString(value.ToString("R", CultureInfo.InvariantCulture));
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(byte value, JsonSerializerHandler handler)
{
WriteValue((int)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(sbyte value, JsonSerializerHandler handler)
{
WriteValue((int)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(short value, JsonSerializerHandler handler)
{
WriteValue((int)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(ushort value, JsonSerializerHandler handler)
{
WriteValue((int)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(bool value, JsonSerializerHandler handler)
{
handler.WriteString(value ? "true" : "false");
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(char value, JsonSerializerHandler handler)
{
WriteValue(char.ToString(value), handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static unsafe void WriteValue(string value, JsonSerializerHandler handler)
{
/*
string = quotation-mark *char quotation-mark
char = unescaped /
escape (
%x22 / ; " quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
escape = %x5C ; \
quotation-mark = %x22 ; "
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
*/
if (value == null)
{
handler.WriteString("null");
return;
}
//handler.Writer.EnsureCapacity(handler.Writer.Capacity + value.Length);
handler.WriteString("\"");
fixed (char* strFixed = value)
{
char* str = strFixed;
char c;
var len = value.Length;
while (len > 0)
{
c = *str;
str++;
len--;
if (c == '\\')//\u005c //%x5c a\\b => a\u005cb
{
handler.WriteString(@"\\");
continue;
}
if (c == '"')//\u0022 //%x22
{
handler.WriteString("\\\"");
continue;
}
switch (c)
{
//%x00-x19
case '\u0000': handler.WriteString(@"\u0000"); continue;
case '\u0001': handler.WriteString(@"\u0001"); continue;
case '\u0002': handler.WriteString(@"\u0002"); continue;
case '\u0003': handler.WriteString(@"\u0003"); continue;
case '\u0004': handler.WriteString(@"\u0004"); continue;
case '\u0005': handler.WriteString(@"\u0005"); continue;
case '\u0006': handler.WriteString(@"\u0006"); continue;
case '\u0007': handler.WriteString(@"\u0007"); continue;
case '\u0008': handler.WriteString(@"\b"); continue;
case '\u0009': handler.WriteString(@"\t"); continue;
case '\u000A': handler.WriteString(@"\n"); continue;
case '\u000B': handler.WriteString(@"\u000b"); continue;
case '\u000C': handler.WriteString(@"\f"); continue;
case '\u000D': handler.WriteString(@"\r"); continue;
case '\u000E': handler.WriteString(@"\u000e"); continue;
case '\u000F': handler.WriteString(@"\u000f"); continue;
case '\u0010': handler.WriteString(@"\u0010"); continue;
case '\u0011': handler.WriteString(@"\u0011"); continue;
case '\u0012': handler.WriteString(@"\u0012"); continue;
case '\u0013': handler.WriteString(@"\u0013"); continue;
case '\u0014': handler.WriteString(@"\u0014"); continue;
case '\u0015': handler.WriteString(@"\u0015"); continue;
case '\u0016': handler.WriteString(@"\u0016"); continue;
case '\u0017': handler.WriteString(@"\u0017"); continue;
case '\u0018': handler.WriteString(@"\u0018"); continue;
case '\u0019': handler.WriteString(@"\u0019"); continue;
case '\u001A': handler.WriteString(@"\u001a"); continue;
case '\u001B': handler.WriteString(@"\u001b"); continue;
case '\u001C': handler.WriteString(@"\u001c"); continue;
case '\u001D': handler.WriteString(@"\u001d"); continue;
case '\u001E': handler.WriteString(@"\u001e"); continue;
case '\u001F': handler.WriteString(@"\u001f"); continue;
/*JavaScript */
case '\u0085': // Next Line
handler.WriteString(@"\u0085"); continue;
case '\u2028': // Line Separator
handler.WriteString(@"\u2028"); continue;
case '\u2029': // Paragraph Separator
handler.WriteString(@"\u2029"); continue;
default: handler.WriteChar(c); continue;
}
}
}
handler.WriteString("\"");
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(IntPtr value, JsonSerializerHandler handler)
{
WriteValue((long)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(UIntPtr value, JsonSerializerHandler handler)
{
WriteValue((ulong)value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[FuncLable(FuncType.SameType)]
internal static void WriteValue(object obj, JsonSerializerHandler handler)
{
if (obj == null)
{
handler.WriteString("null");
return;
}
var type = obj.GetType();
if (type.IsAnonymousType() || type == typeof(object))
SpecialConditions.WriteDynamic(obj, handler);
else
{
var jumpAction = SerializerObjectJump.GetThreadSafetyJumpAction(type);
jumpAction(obj, handler);
}
}
}
}

View File

@ -0,0 +1,283 @@
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace CPF.Json.Serializer
{
internal class SpecialConditions : DefaultJsonFormatter
{
#region pregenerated metas
internal static MethodInfo _WriteEnum = typeof(SpecialConditions).GetMethod(nameof(WriteEnum), BindingFlags.NonPublic | BindingFlags.Static);
#endregion
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteDynamic(object value, JsonSerializerHandler handler)
{
if (value == null)
{
handler.WriteString("null");
return;
}
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
{
if (handler.SerializeStacks.Contains(value))
{
if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Null)
handler.WriteString("null");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Empty)
handler.WriteString("{}");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Remove)
RemoveWriterHelper.RemoveDictionaryKey(handler);
return;
}
handler.SerializeStacks.Push(value);
}
var t = value.GetType();
handler.WriteString("{");
bool isFirst = true;
foreach (var item in t.GetProperties())
{
if (isFirst)
isFirst = false;
else
handler.WriteString(",");
handler.WriteString("\"");
handler.WriteString(item.Name);
handler.WriteString("\"");
handler.WriteString(":");
#if Net4
SerializerObjectJump.GetThreadSafetyJumpAction(item.PropertyType)(item.GetValue(value, null), handler);
#else
SerializerObjectJump.GetThreadSafetyJumpAction(item.PropertyType)(item.GetValue(value), handler);
#endif
}
handler.WriteString("}");
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void AvoidTypes(object typeVar, JsonSerializerHandler handler)
{
handler.WriteString(typeVar == null ? "null" : "{}");
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteEnum(Enum value, JsonSerializerHandler handler)
{
if (handler.Option.IsEnumNum)
PrimitiveNormal.WriteValue(value.GetHashCode(), handler);
else
{
handler.WriteString("\"");
handler.WriteString(value.ToString());
handler.WriteString("\"");
}
}
#region Array
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteCollection(IEnumerable value, JsonSerializerHandler handler)
{
if (value == null)
{
handler.WriteString("null");
return;
}
var t = value.GetType();
if (t.IsGenericType)
{
var serializerAction = SerializerObjectJump.GetThreadSafetyJumpAction(t);
serializerAction(value, handler);
}
else
{
bool isMultidimensionalArray = false;
Array ary = null;
if (t.IsArray)
{
ary = (Array)value;
if (ary.Rank > 1)
isMultidimensionalArray = true;
}
if (isMultidimensionalArray)
WriteMultidimensionalArray(ary, handler);
else
WriteIEnumerable(value, handler);
}
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteIEnumerable(IEnumerable value, JsonSerializerHandler handler)
{
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
{
if (handler.SerializeStacks.Contains(value))
{
if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Null)
handler.WriteString("null");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Empty)
handler.WriteString("[]");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Remove)
RemoveWriterHelper.RemoveArrayItem(handler);
return;
}
handler.SerializeStacks.Push(value);
}
handler.WriteString("[");
bool isFirst = true;
foreach (var obj in value)
{
if (isFirst)
isFirst = false;
else
handler.WriteString(",");
PrimitiveNormal.WriteValue(obj, handler);
}
handler.WriteString("]");
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
handler.SerializeStacks.Pop();
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteMultidimensionalArray(Array value, JsonSerializerHandler handler)
{
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
{
if (handler.SerializeStacks.Contains(value))
{
if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Null)
handler.WriteString("null");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Empty)
handler.WriteString("[]");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Remove)
RemoveWriterHelper.RemoveArrayItem(handler);
return;
}
handler.SerializeStacks.Push(value);
}
var action = SerializerObjectJump.GetThreadSafetyJumpAction(value.GetType().GetElementType());
handler.WriteString("[");
var enumerator = value.GetEnumerator();
MultidimensionalWrite(enumerator, handler, value, action, value.GetLength(0), 0);
handler.WriteString("]");
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
handler.SerializeStacks.Pop();
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static void MultidimensionalWrite(IEnumerator enumerator, JsonSerializerHandler handler, Array value, Action<object, JsonSerializerHandler> action, int leng, int level)
{
for (int i = 0; i < leng; i++)
{
if (level != value.Rank - 1)
handler.WriteString("[");
if (level == value.Rank - 1)
{
enumerator.MoveNext();
action(enumerator.Current, handler);
if (i != leng - 1)
handler.WriteString(",");
continue;
}
int localLevel = level;
++localLevel;
MultidimensionalWrite(enumerator, handler, value, action, value.GetLength(localLevel), localLevel);
handler.WriteString("]");
if (i != leng - 1)
handler.WriteString(",");
}
}
#endregion
#region Dictionary
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteDictionary(IDictionary value, JsonSerializerHandler handler)
{
if (value == null)
{
handler.WriteString("null");
return;
}
var t = value.GetType();
if (t.IsGenericType)
{
var serializerAction = SerializerObjectJump.GetThreadSafetyJumpAction(t);
serializerAction(value, handler);
}
else
WriteIDictionary(value, handler);
}
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void WriteIDictionary(IDictionary value, JsonSerializerHandler handler)
{
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
{
if (handler.SerializeStacks.Contains(value))
{
if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Null)
handler.WriteString("null");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Empty)
handler.WriteString("{}");
else if (handler.Option.ReferenceLoopHandling == JsonReferenceHandlingEnum.Remove)
RemoveWriterHelper.RemoveDictionaryKey(handler);
return;
}
handler.SerializeStacks.Push(value);
}
bool isFirst = true;
handler.WriteString("{");
foreach (DictionaryEntry item in value)
{
var keyType = item.Key.GetType();
if (keyType.IsWrongKey())
continue;
if (isFirst)
isFirst = false;
else
handler.WriteString(",");
if (keyType.IsPrimitive || (keyType.IsEnum && handler.Option.IsEnumNum))//string,primitive,enum,guid,datetime
handler.WriteString("\"");
PrimitiveNormal.WriteValue(item.Key, handler);
if (keyType.IsPrimitive || (keyType.IsEnum && handler.Option.IsEnumNum))
handler.WriteString("\"");
handler.WriteString(":");
PrimitiveNormal.WriteValue(item.Value, handler);
}
handler.WriteString("}");
if (handler.Option.ReferenceLoopHandling != JsonReferenceHandlingEnum.None)
handler.SerializeStacks.Pop();
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
namespace CPF.Json.Serializer
{
internal class DefaultJsonFormatter : JsonFormatterBase
{
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Serializer
{
internal class BuildFactory
{
static BuildFactory()
{
var types = SerializerBootTable.Table.ExpressionBuildTypes;
foreach (var item in types)
{
ExpressionBuildTypeAttribute expressionBuildTypeAttribute = (ExpressionBuildTypeAttribute)item.GetCustomAttributes(false).First(e => e.GetType() == typeof(ExpressionBuildTypeAttribute));
BuildMethodDics.Add(expressionBuildTypeAttribute._serializerBuildTypeEnum, item.GetMethod("Build", BindingFlags.Static | BindingFlags.NonPublic));
}
SerializerBootTable.Table.ExpressionBuildTypes = null;
}
internal static Dictionary<Type, Expression> DEBUGSURVEY = new Dictionary<Type, Expression>();
static Dictionary<SerializerBuildTypeEnum, MethodInfo> BuildMethodDics = new Dictionary<SerializerBuildTypeEnum, MethodInfo>();
internal static Action<T, JsonSerializerHandler> Create<T>(SerializerBuildTypeEnum buildTypeEnum)
{
Type t = typeof(T);
ParameterExpression instanceArg = Expression.Variable(t, "instance");
Expression mainBody = (Expression)BuildMethodDics[buildTypeEnum].Invoke(null, new object[] { t, instanceArg });
#if DEBUG
DEBUGSURVEY.Add(t, mainBody);
#endif
#if VIEW && NET45
var methodBuilder = typeBuilder.DefineMethod($"Serializer_{typeof(T).Name}", System.Reflection.MethodAttributes.Static | System.Reflection.MethodAttributes.Public, typeof(void), new Type[] { typeof(T), typeof(JsonSerializerHandler) });
Expression.Lambda<Action<T, JsonSerializerHandler>>(
mainBody, instanceArg, ExpressionMembers.HandlerArg).CompileToMethod(methodBuilder);
#endif
return Expression.Lambda<Action<T, JsonSerializerHandler>>(
mainBody, instanceArg, ExpressionMembers.HandlerArg).Compile();
}
#if VIEW && NET45
#if DEBUG
static string suffix = "_Debug";
#else
static string suffix = "_Release";
#endif
static string name = $"Serializer_CodeView{suffix}";
static System.Reflection.Emit.AssemblyBuilder assemblyBuilder = System.Reflection.Emit.AssemblyBuilder.DefineDynamicAssembly(new System.Reflection.AssemblyName(name), System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
static System.Reflection.Emit.ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, name + ".dll");
static System.Reflection.Emit.TypeBuilder typeBuilder = moduleBuilder.DefineType("Program");
#endif
internal static void Save()
{
#if VIEW && NET45
typeBuilder.CreateType();
assemblyBuilder.Save(name + ".dll");
#endif
}
}
}

View File

@ -0,0 +1,15 @@

namespace CPF.Json.Serializer
{
internal enum SerializerBuildTypeEnum
{
Nullable,
IDictionaryGeneric,
IEnumerableGeneric,
IListGeneric,
WrongGenericKey,
KeyValueObject,
KeyValuePair,
Lazy
}
}

View File

@ -0,0 +1,188 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace CPF.Json.Serializer
{
internal class ExpressionMembers
{
//- handler;
internal static ParameterExpression HandlerArg = Expression.Parameter(typeof(JsonSerializerHandler), "handler");
//- return(label);
internal static readonly LabelTarget ReturnLable = Expression.Label(typeof(void));
//- handler.WriteString
internal static readonly MemberExpression WriteString = Expression.MakeMemberAccess(HandlerArg, JsonSerializerHandler._WriteString);
//- handler.option;
internal static readonly MemberExpression JOptionArg = Expression.MakeMemberAccess(HandlerArg, JsonSerializerHandler._Option);
//- handler.serializeStacks
internal static readonly MemberExpression SerializeStacksArg = Expression.MakeMemberAccess(HandlerArg, JsonSerializerHandler._SerializeStacks);
//- handler.option.GlobalKeyFormat(delegate)
internal static readonly MemberExpression GlobalKeyFormat = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._GlobalKeyFormat);
//- handler.option.GlobalValueFormat(delegate)
internal static readonly MemberExpression GlobalValueFormat = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._GlobalValueFormat);
//- afterValueFormat(string)
internal static readonly ParameterExpression AfterValueFormat = Expression.Variable(typeof(string), "afterValueFormat");
//- isValueFormat(bool)
internal static readonly ParameterExpression IsValueFormat = Expression.Variable(typeof(bool), "isValueFormat");
//- handler.option.ignoreKeys(List<string>)
internal static readonly MemberExpression IgnoreKeys = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._IgnoreKeys);
//- handler.option.ignoreKeys == null
internal static readonly BinaryExpression IgnoreKeysIsNull = Expression.Equal(IgnoreKeys, Expression.Constant(null));
//- handler.option.ignoreKeys != null
internal static readonly BinaryExpression IgnoreKeysIsNotNull = Expression.NotEqual(IgnoreKeys, Expression.Constant(null));
//- handler.option.ignoreKeys.count() == 0
internal static readonly BinaryExpression IgnoreKeysCountIsZero = Expression.Equal(Expression.MakeMemberAccess(IgnoreKeys, typeof(List<string>).GetProperty("Count")), Expression.Constant(0));
//- handler.option.jsonCharacterRead(Enum)
internal static readonly MemberExpression JsonCharacterRead = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._JsonCharacterRead);
//- handler.option.isEnumNum(bool)
internal static readonly MemberExpression IsEnumNum = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._IsEnumNum);
//- handler.option.isIgnoreValueNull(bool)
internal static readonly UnaryExpression IgnoreValueNullIsTrue = Expression.IsTrue(Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._IsIgnoreValueNull));
//- handler.option.referenceLoopHandling(Enum)
internal static readonly MemberExpression ReferenceLoopHandling = Expression.MakeMemberAccess(JOptionArg, JsonSerializerOption._ReferenceLoopHandling);
//- handler.option.referenceLoopHandling != Enum.None
internal static readonly BinaryExpression IsReferenceLoopHandlingNotEqualsNone = Expression.NotEqual(ReferenceLoopHandling, Expression.Constant(JsonReferenceHandlingEnum.None));
//- handler.option.referenceLoopHandling == Enum.Remove
internal static readonly BinaryExpression IsReferenceLoopHandlingEqualsRemove = Expression.Equal(ReferenceLoopHandling, Expression.Constant(JsonReferenceHandlingEnum.Remove));
//- handler.option.referenceLoopHandling == Enum.Empty
internal static readonly BinaryExpression IsReferenceLoopHandlingEqualsEmpty = Expression.Equal(ReferenceLoopHandling, Expression.Constant(JsonReferenceHandlingEnum.Empty));
//- handler.option.referenceLoopHandling == Enum.Null
internal static readonly BinaryExpression IsReferenceLoopHandlingEqualsNull = Expression.Equal(ReferenceLoopHandling, Expression.Constant(JsonReferenceHandlingEnum.Null));
//- handler.commaIndexLists
internal static readonly MemberExpression ListCommaIndexs = Expression.MakeMemberAccess(HandlerArg, JsonSerializerHandler._CommaIndexLists);
//if ( referenceLoopHandling == Enum.Remove ) ==> DeleteComma()
internal static readonly ConditionalExpression IsReferenceLoopHandlingIsRemoveDeleteComma = Expression.IfThen(
IsReferenceLoopHandlingEqualsRemove,
DeleteComma()
);
//if ( referenceLoopHandling == Enum.None ) ==> serializeStacks.Pop()
internal static readonly ConditionalExpression IsReferenceLoopHandlingIsNoneSerializeStacksArgPop = Expression.IfThen(
IsReferenceLoopHandlingNotEqualsNone,
Expression.Call(SerializeStacksArg, typeof(Stack<object>).GetMethod("Pop"))
);
//call
internal static readonly MethodCallExpression WriteLeft = Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Constant("{"));
internal static readonly MethodCallExpression WriteRight = Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Constant("}"));
internal static readonly MethodCallExpression WriteComma = Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Constant(","));
internal enum RefernceByEmptyType
{
Array,
Dictionary,
CustomType
}
internal static Expression WriteKeyValuePairKey(Type keyType, Expression key)
{
List<Expression> calls = new List<Expression>();
if (keyType == typeof(string) || keyType == typeof(Guid) || keyType == typeof(DateTime))
{
calls.Add(GetMethodCall(keyType, key));
calls.Add(Append(":"));
}
else if (keyType.IsPrimitive)
{
calls.Add(Append("\""));
calls.Add(Expression.Call(SerializerBootTable.Table.DefaultSameTypes[keyType], key, HandlerArg));
calls.Add(Append("\":"));
}
else if (keyType.IsEnum)//The default is tostring
{
calls.Add(Append("\""));
calls.Add(Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Call(key, typeof(Enum).GetMethod("ToString", new Type[0]))));
calls.Add(Append("\":"));
}
return Expression.Block(calls);
}
internal static Expression IsIgnoreSelfRefernce(ParameterExpression instanceArg, RefernceByEmptyType emptyType)
{
MethodCallExpression contains = Expression.Call(SerializeStacksArg, typeof(Stack<object>).GetMethod("Contains", new[] { typeof(object) }), Expression.Convert(instanceArg, typeof(object)));
MethodCallExpression call;
if (emptyType == RefernceByEmptyType.Array)
call = RemoveArrayItem();
else if (emptyType == RefernceByEmptyType.Dictionary)
call = RemoveDictionaryKey();
else
call = RemoveKeyAndAddIndex();
BlockExpression containsBody = Expression.Block(
Expression.IfThenElse(
IsReferenceLoopHandlingEqualsNull, Append("null"),
Expression.IfThenElse(
IsReferenceLoopHandlingEqualsEmpty, Append(emptyType == RefernceByEmptyType.Array ? "[]" : "{}"),
call)
),
Expression.Return(ReturnLable)
);
ConditionalExpression ifContainsBlock = Expression.IfThen(contains, containsBody);
// handler.serializeStacks.Push(value);
MethodCallExpression push = Expression.Call(SerializeStacksArg, typeof(Stack<object>).GetMethod("Push", new[] { typeof(object) }), Expression.Convert(instanceArg, typeof(object)));
ConditionalExpression isIgnoreSelfRefernce = Expression.IfThen(IsReferenceLoopHandlingNotEqualsNone,
Expression.Block(
ifContainsBlock, push
));
return isIgnoreSelfRefernce;
}
internal static MethodCallExpression GetMethodCall(Type type, Expression member)
{
return Expression.Call(typeof(FormattingProvider<>).MakeGenericType(type).GetMethod("Convert", BindingFlags.NonPublic | BindingFlags.Static), member, HandlerArg);
}
internal static MethodCallExpression AppendKey(string str)
{
return Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Constant("\"" + str + "\":"));
}
internal static MethodCallExpression Append(string str)
{
return Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Constant(str));
}
internal static MethodCallExpression Append(Expression strExpression)
{
return Expression.Call(WriteString, JsonSerializerHandler._WriteStringInvoke, strExpression);
}
internal static MethodCallExpression RemoveDictionaryKey()
{
return Expression.Call(RemoveWriterHelper._RemoveDictionaryKey, HandlerArg);
}
internal static MethodCallExpression RemoveArrayItem()
{
return Expression.Call(RemoveWriterHelper._RemoveArrayItem, HandlerArg);
}
internal static MethodCallExpression RemoveKeyAndAddIndex()
{
return Expression.Call(RemoveWriterHelper._RemoveKeyAndAddIndex, HandlerArg, ListCommaIndexs);
}
internal static MethodCallExpression RemoveLastComma()
{
return Expression.Call(RemoveWriterHelper._RemoveLastComma, HandlerArg);
}
internal static MethodCallExpression DeleteComma()
{
return Expression.Call(RemoveWriterHelper._DeleteComma, HandlerArg, ListCommaIndexs);
}
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.IDictionaryGeneric)]
internal class IDictionaryGenericBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 0)
{
Type idic = type.GetInterface("IDictionary`2");
genericArguments = idic.GetGenericArguments();
}
Type keyType = genericArguments[0];
Type valueType = genericArguments[1];
List<Expression> methodCall = new List<Expression>();
if (!type.IsValueType)
{
ConditionalExpression ifNullAppendNull = Expression.IfThen(
Expression.Equal(instanceArg, Expression.Constant(null, type)),
Expression.Block(ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
));
methodCall.Add(ifNullAppendNull);
}
methodCall.Add(ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.Dictionary));
methodCall.Add(ExpressionMembers.Append("{"));
ParameterExpression isFirst = Expression.Variable(typeof(bool), "isFirst");
Expression foreachs = ExpressionHelper.ForEach(instanceArg, Expression.Parameter(typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType), "loopVar"),
item =>
{
List<Expression> calls = new List<Expression>
{
Expression.IfThenElse(
Expression.IsFalse(isFirst),
Expression.Assign(isFirst, Expression.Constant(true)),
ExpressionMembers.Append(",")
)
};
MemberExpression key = Expression.MakeMemberAccess(item, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Key"));
MemberExpression value = Expression.MakeMemberAccess(item, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Value"));
calls.Add(ExpressionMembers.WriteKeyValuePairKey(keyType, key));
calls.Add(ExpressionMembers.GetMethodCall(valueType, value));
return Expression.Block(new[] { isFirst }, calls);
}
);
methodCall.Add(foreachs);
methodCall.Add(ExpressionMembers.Append("}"));
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(methodCall);
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.IEnumerableGeneric)]
internal class IEnumerableGenericBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Type arrayItemType = type.GetElementType();
if (arrayItemType == null)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 0)
arrayItemType = type.GetInterface("IEnumerable`1").GetGenericArguments()[0];
else
arrayItemType = genericArguments[0];
}
List<Expression> methodCall = new List<Expression>();
if (!type.IsValueType)
{
ConditionalExpression ifNullAppendNull = Expression.IfThen(
Expression.Equal(instanceArg, Expression.Constant(null,type)),
Expression.Block(ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
));
methodCall.Add(ifNullAppendNull);
}
methodCall.Add(ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.Array));
methodCall.Add(ExpressionMembers.Append("["));
ParameterExpression isFirst = Expression.Variable(typeof(bool), "isFirst");
Expression foreachs = ExpressionHelper.ForEach(instanceArg, Expression.Parameter(arrayItemType, "loopVar"),
item => Expression.Block(new[] { isFirst },
Expression.IfThenElse(
Expression.IsFalse(isFirst),
Expression.Assign(isFirst, Expression.Constant(true)),
ExpressionMembers.Append(",")
),
ExpressionMembers.GetMethodCall(arrayItemType, item)
));
methodCall.Add(foreachs);
methodCall.Add(ExpressionMembers.Append("]"));
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(methodCall);
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.IListGeneric)]
internal class IListGenericBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Type arrayItemType = type.GetElementType();
if (arrayItemType == null)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 0)
arrayItemType = type.GetInterface("IList`1").GetGenericArguments()[0];
else
arrayItemType = genericArguments[0];
}
List<Expression> methodCall = new List<Expression>();
if (!type.IsValueType)
{
ConditionalExpression ifNullAppendNull = Expression.IfThen(
Expression.Equal(instanceArg, Expression.Constant(null, type)),
Expression.Block(ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
));
methodCall.Add(ifNullAppendNull);
}
methodCall.Add(ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.Array));
methodCall.Add(ExpressionMembers.Append("["));
ParameterExpression isFirst = Expression.Variable(typeof(bool), "isFirst");
Type iListType = typeof(IList<>).MakeGenericType(arrayItemType);
ParameterExpression iList = Expression.Variable(iListType);
methodCall.Add(Expression.Assign(iList, Expression.Convert(instanceArg, iListType)));
ParameterExpression forVariable = Expression.Variable(typeof(int));
//Expression forExpression = ExpressionHelper.For(forVariable, Expression.LessThan(forVariable, Expression.MakeMemberAccess(instanceArg, type.IsArray ? type.GetProperty("Length") : type.GetProperty("Count"))), Expression.PostIncrementAssign(forVariable), Expression.Block(new[] { isFirst },
// Expression.IfThenElse(
// Expression.IsFalse(isFirst),
// Expression.Assign(isFirst, Expression.Constant(true)),
// ExpressionMembers.Append(",")
// ),
// ExpressionMembers.GetMethodCall(arrayItemType, type.IsArray ? Expression.ArrayAccess(instanceArg, forVariable) : Expression.MakeIndex(instanceArg, type.GetProperty("Item"), new[] { forVariable }))
// ));
Expression forExpression = ExpressionHelper.For(forVariable, Expression.LessThan(forVariable, Expression.MakeMemberAccess(instanceArg, type.IsArray ? type.GetProperty("Length") : type.GetProperty("Count"))), Expression.PostIncrementAssign(forVariable), Expression.Block(new[] { isFirst },
Expression.IfThenElse(
Expression.IsFalse(isFirst),
Expression.Assign(isFirst, Expression.Constant(true)),
ExpressionMembers.Append(",")
),
ExpressionMembers.GetMethodCall(arrayItemType, Expression.MakeIndex(iList, iListType.GetProperty("Item"), new[] { forVariable }))
));
methodCall.Add(forExpression);
methodCall.Add(ExpressionMembers.Append("]"));
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(new[] { iList }, methodCall);
}
}
}

View File

@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.KeyValueObject)]
internal class KeyValueObjectBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
List<Expression> methodCall = new List<Expression>();
if (!type.IsValueType)
{
ConditionalExpression ifParaIsNullAppendNull = Expression.IfThen(Expression.Equal(instanceArg, Expression.Constant(null, type)),
Expression.Block(
ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
));
methodCall.Add(ifParaIsNullAppendNull);//add
Expression isIgnoreSelfRefernceModule = ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.CustomType);
methodCall.Add(isIgnoreSelfRefernceModule);//add
}
methodCall.Add(ExpressionMembers.WriteLeft);
var elements = type.GetModelMembers(ReadMemberStateEnum.CanRead);
bool hasIgnoreDefaultValueAttribute = false;
for (int i = 0; i < elements.Count; i++)
{
var item = elements[i];
//valueformat
ValueFormatAttribute valueformat = item.Value.MemberInfo.GetCustomAttribute<ValueFormatAttribute>() ??
item.Value.MemberInfo.DeclaringType.GetCustomAttribute<ValueFormatAttribute>();
//IgnoreDefaultValue
IgnoreDefaultValueAttribute ignoreDefaultValue = item.Value.MemberInfo.GetCustomAttribute<IgnoreDefaultValueAttribute>() ??
item.Value.MemberInfo.DeclaringType.GetCustomAttribute<IgnoreDefaultValueAttribute>();
if (ignoreDefaultValue != null)
hasIgnoreDefaultValueAttribute = true;
//if (!(m.Name == null && handler.option.IsIgnoreNull))//0
MemberExpression mName = Expression.MakeMemberAccess(instanceArg, item.Value.MemberInfo);
// if (option1.IsFirstLower)
string lowerName = item.Key.Substring(0, 1).ToLower() + item.Key.Substring(1);
string upperName = item.Key.Substring(0, 1).ToUpper() + item.Key.Substring(1);
/*
ignoreKeys == null || ignoreKeys.count() == 0 || ignoreKeys.Contains(name)==false
*/
BinaryExpression ignoreKeysJudge = Expression.OrElse(
ExpressionMembers.IgnoreKeysIsNull,
Expression.OrElse(
ExpressionMembers.IgnoreKeysCountIsZero,
Expression.Equal(
Expression.Call(ExpressionMembers.IgnoreKeys, typeof(List<string>).GetMethod("Contains"), Expression.Constant(item.Key))
, Expression.Constant(false))
));
/*
(ignoreKeys == null || ignoreKeys.count() == 0 || ignoreKeys.Contains(name)==false) && ( m!=default(m) )
*/
if (ignoreDefaultValue != null)
ignoreKeysJudge = Expression.AndAlso(ignoreKeysJudge, Expression.NotEqual(mName, Expression.Constant(item.Value.Type.GetDefaultValue(), item.Value.Type)));
/*
if(option.keyformat!=null)
$handler.WriteString("\"");
$handler.WriteString(option.keyformat.invoke(string));
append("\":")
else
{
switch(JsonCharacterRead)
{
case None:
AppendKey()
case InitialUpper:
..
case InitialLower:
..
}
}
};
*/
Expression writeKey = Expression.IfThenElse(Expression.NotEqual(ExpressionMembers.GlobalKeyFormat, Expression.Constant(null, JsonSerializerOption._GlobalKeyFormat.FieldType)),
Expression.Block(
ExpressionMembers.Append("\""),
Expression.Call(ExpressionMembers.WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Call(ExpressionMembers.GlobalKeyFormat, JsonSerializerOption._GlobalKeyFormatInvoke, Expression.Constant(item.Key), Expression.Constant(type, typeof(Type)), ExpressionMembers.HandlerArg)
),
ExpressionMembers.Append("\":")
),
Expression.Switch(typeof(void), ExpressionMembers.JsonCharacterRead, null, null,
Expression.SwitchCase(ExpressionMembers.AppendKey(item.Key), Expression.Constant(JsonCharacterReadStateEnum.None, typeof(JsonCharacterReadStateEnum))),
Expression.SwitchCase(ExpressionMembers.AppendKey(upperName), Expression.Constant(JsonCharacterReadStateEnum.InitialUpper, typeof(JsonCharacterReadStateEnum))),
Expression.SwitchCase(ExpressionMembers.AppendKey(lowerName), Expression.Constant(JsonCharacterReadStateEnum.InitialLower, typeof(JsonCharacterReadStateEnum)))
)
);
/*
string afterValueFormat= valueformat.WriteValueFormat( model.Name,hander out isValueFormat)
if(isValueFormat)
sb.append(afterValueFormat)
else
WriteValue(model.Name,handler)
*/
Expression writeValue;
if (valueformat != null)
{
writeValue = Expression.Block(
Expression.NotEqual(ExpressionMembers.GlobalValueFormat, Expression.Constant(null, JsonSerializerOption._GlobalValueFormat.FieldType)),
Expression.Assign(ExpressionMembers.AfterValueFormat, Expression.Call(Expression.Constant(valueformat, typeof(ValueFormatAttribute)), ValueFormatAttribute._WriteValueFormat, Expression.Convert(mName, typeof(object)), Expression.Constant(item.Value.Type, typeof(Type)), ExpressionMembers.HandlerArg, ExpressionMembers.IsValueFormat)),
Expression.IfThenElse(Expression.IsTrue(ExpressionMembers.IsValueFormat), ExpressionMembers.Append(ExpressionMembers.AfterValueFormat), ExpressionMembers.GetMethodCall(item.Value.Type, mName))
);
}
else
{
/*
if( option.GlobalValueFormat!=null){
string afterValueFormat= option.GlobalValueFormat.Invoke( model.Name,hander out isValueFormat)
if(isValueFormat)
sb.append(afterValueFormat)
else
WriteValue(model.Name,handler)
}
else
{
WriteValue(model.Name,handler)
}
*/
writeValue = Expression.IfThenElse(
Expression.NotEqual(ExpressionMembers.GlobalValueFormat, Expression.Constant(null, JsonSerializerOption._GlobalValueFormat.FieldType)),
Expression.Block(
Expression.Assign(ExpressionMembers.AfterValueFormat, Expression.Call(ExpressionMembers.GlobalValueFormat, JsonSerializerOption._GlobalValueFormatInvoke, Expression.Convert(mName, typeof(object)), Expression.Constant(item.Value.Type, typeof(Type)), ExpressionMembers.HandlerArg, ExpressionMembers.IsValueFormat)),
Expression.IfThenElse(Expression.IsTrue(ExpressionMembers.IsValueFormat), ExpressionMembers.Append(ExpressionMembers.AfterValueFormat), ExpressionMembers.GetMethodCall(item.Value.Type, mName))
),
ExpressionMembers.GetMethodCall(item.Value.Type, mName)
);
}
Expression trunk = Expression.Block(writeKey, writeValue);
// json.Append(",");
if (i != elements.Count - 1)
trunk = Expression.Block(trunk, ExpressionMembers.WriteComma);
if (!item.Value.Type.IsValueType || (item.Value.Type.IsGenericType && item.Value.Type.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
BinaryExpression mNameIsNull = Expression.Equal(mName, Expression.Constant(null));
//if(!null&&isgorenull)
trunk = Expression.IfThen(Expression.IsFalse(Expression.And(mNameIsNull, ExpressionMembers.IgnoreValueNullIsTrue)), trunk);
}
//
trunk = Expression.IfThen(ignoreKeysJudge, trunk);//忽略key
methodCall.Add(trunk);
}
// //if ( ignoreValueNull == true || ignoreKeys!=null ) ==> RemoveLastComma()
var IgnoreValueNullIsTrueOrIgnoreKeysNotEqureNullRemoveLastComma = Expression.IfThen(
Expression.OrElse(ExpressionMembers.IgnoreValueNullIsTrue, ExpressionMembers.IgnoreKeysIsNotNull),
ExpressionMembers.RemoveLastComma()
);
methodCall.Add(hasIgnoreDefaultValueAttribute? (Expression)ExpressionMembers.RemoveLastComma():IgnoreValueNullIsTrueOrIgnoreKeysNotEqureNullRemoveLastComma);
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsRemoveDeleteComma);
methodCall.Add(ExpressionMembers.WriteRight);
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(new[] { ExpressionMembers.AfterValueFormat, ExpressionMembers.IsValueFormat }, methodCall);
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.KeyValuePair)]
internal class KeyValuePairBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Type keyType = type.GetGenericArguments()[0];
Type valueType = type.GetGenericArguments()[1];
Expression[] methodCall = new Expression[7];
methodCall[0] = ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.Dictionary);
methodCall[1] = ExpressionMembers.Append("{");
MemberExpression key = Expression.MakeMemberAccess(instanceArg, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Key"));
MemberExpression value = Expression.MakeMemberAccess(instanceArg, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Value"));
methodCall[2] = ExpressionMembers.WriteKeyValuePairKey(keyType, key);
methodCall[3] = ExpressionMembers.GetMethodCall(valueType, value);
methodCall[4] = ExpressionMembers.Append("}");
methodCall[5] = ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop;
methodCall[6] = Expression.Label(ExpressionMembers.ReturnLable);
return Expression.Block(methodCall);
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.Lazy)]
internal class LazyBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Expression orginal = ExpressionMembers.GetMethodCall(type.GetGenericArguments()[0], Expression.MakeMemberAccess(instanceArg, type.GetProperty("Value")));
return Expression.IfThenElse(
Expression.Equal(instanceArg, Expression.Constant(null,type)),
ExpressionMembers.Append("null")
,
//para.value
orginal
);
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.Nullable)]
internal class NullableBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Expression orginal = ExpressionMembers.GetMethodCall(type.GetGenericArguments()[0], Expression.MakeMemberAccess(instanceArg, type.GetProperty("Value")));
return Expression.IfThenElse(
Expression.Equal(instanceArg, Expression.Constant(null,type)),
ExpressionMembers.Append("null")
,
//para.value
orginal
);
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.WrongGenericKey)]
internal class WrongGenericKeyBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
List<Expression> expressions = new List<Expression>();
if (!type.IsValueType)
expressions.Add(Expression.IfThen(
Expression.Equal(instanceArg, Expression.Constant(null,type)),
Expression.Block(ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
)));
expressions.Add(ExpressionMembers.Append("{}"));
expressions.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(expressions);
}
}
}

View File

@ -0,0 +1,6 @@
namespace CPF.Json.Serializer
{
internal class ExpressionJsonFormatter :JsonFormatterBase
{
}
}

View File

@ -0,0 +1,462 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace CPF.Json.Serializer
{
internal class FormatterFind<T>
{
internal static Action<T, JsonSerializerHandler> Find()
{
Type t = typeof(T);
return FindTypeIsDefaultImplemented(t) ?? FindTypeIsMeetDefaultCondition(t) ?? FindTypeIsDefaultImplementedBaseType(t) ?? FindTypeIsDefaultImplementedInterface(t) ?? DefaultResolve(t);
}
private static Action<T, JsonSerializerHandler> FindTypeIsDefaultImplemented(Type t)
{
if (SerializerBootTable.Table.DefaultSameTypes.TryGetValue(t, out MethodInfo value))
return GenerateLambdaCall(value);
return null;
}
private static Action<T, JsonSerializerHandler> FindTypeIsMeetDefaultCondition(Type t)
{
return IsLoadDynamic(t) ?? IsArray(t) ?? IsEnum(t);
}
private static Action<T, JsonSerializerHandler> FindTypeIsDefaultImplementedBaseType(Type t)
{
var baseTypes = t.GetTypeAndBaseTypes();
//Avoid
if (SerializerBootTable.Table.DefaultAvoidTypes.Intersect(baseTypes).Any())
return (a, b) => SpecialConditions.AvoidTypes(a, b);
//Default
foreach (var implementedType in SerializerBootTable.Table.DefaultImplementedBaseType)
{
foreach (var baseType in baseTypes)
{
if (baseType == implementedType.Key)
{
return GenerateLambdaCall(implementedType.Value.MethodInfo);
}
}
}
return null;
}
private static Action<T, JsonSerializerHandler> FindTypeIsDefaultImplementedInterface(Type t)
{
var intserfaces = t.GetInterfaces().ToList();
if (t.IsInterface)
intserfaces.Add(t);
foreach (var item in SerializerBootTable.Table.DefaultImplementedInterfaces)
{
foreach (var objInterface in intserfaces)
{
if (objInterface == item.Key)
{
return GenerateLambdaCall(item.Value.MethodInfo);
}
}
}
return null;
}
private static Action<T, JsonSerializerHandler> DefaultResolve(Type t)
{
Func<Action<T, JsonSerializerHandler>> func = TypeIsDictionary(t) ?? TypeIsCollection(t) ?? TypeIsSpecial(t);
if (func != null)
return func();
return BuildFactory.Create<T>(SerializerBuildTypeEnum.KeyValueObject);
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsDictionary(Type t)
{
return TypeIsDictionaryInterface(t) ?? TypeIsDictionaryType(t);
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsDictionaryInterface(Type t)
{
if (t == typeof(IDictionary))
return () => (obj, handler) => SpecialConditions.WriteDictionary((IDictionary)obj, handler);
if (t.IsGenericType)
{
Type[] args = t.GetGenericArguments();
if (args.Length != 2)
return null;
var genericTypeDefinition = t.GetGenericTypeDefinition();
var keyType = args[0];
var valueType = args[1];
if (genericTypeDefinition == typeof(IDictionary<,>)
#if !Net4
|| genericTypeDefinition == typeof(IReadOnlyDictionary<,>)
#endif
)
return () => IsWrongKeyType(keyType) ?? BuildFactory.Create<T>(SerializerBuildTypeEnum.IDictionaryGeneric);
}
return null;
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsDictionaryType(Type t)
{
if (t.IsInterface)
return null;
var intserfaces = t.GetInterfaces();
bool hasIDictionaryGeneric = false;
bool hasIDictionary = false;
Type iDictionaryGenericType = null;
Type keyType = null;
Type valueType = null;
foreach (var item in intserfaces)
{
if (item.IsGenericType)
{
var genericTypeDefinition = item.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IDictionary<,>))
{
iDictionaryGenericType = item;
hasIDictionaryGeneric = true;
keyType = item.GetGenericArguments()[0];
valueType = item.GetGenericArguments()[1];
}
}
if (item == typeof(IDictionary))
hasIDictionary = true;
}
if (hasIDictionaryGeneric)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iDictionaryGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (TypeIsDictionary(firstCtor.ParameterType) != null)
{
return () => IsWrongKeyType(keyType) ?? BuildFactory.Create<T>(SerializerBuildTypeEnum.IDictionaryGeneric);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => IsWrongKeyType(keyType) ?? BuildFactory.Create<T>(SerializerBuildTypeEnum.IDictionaryGeneric);
}
else
return () => IsWrongKeyType(keyType) ?? BuildFactory.Create<T>(SerializerBuildTypeEnum.IDictionaryGeneric);
}
if (hasIDictionary)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IDictionary));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (TypeIsDictionary(firstCtor.ParameterType) != null)
{
return () => (obj, handler) => SpecialConditions.WriteDictionary((IDictionary)obj, handler);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => (obj, handler) => SpecialConditions.WriteDictionary((IDictionary)obj, handler);
}
else
return () => (obj, handler) => SpecialConditions.WriteDictionary((IDictionary)obj, handler);
}
return null;
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsCollection(Type t)
{
return TypeIsCollectionInterface(t) ?? TypeIsCollectionType(t);
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsCollectionInterface(Type t)
{
if (t == typeof(IEnumerable) || t == typeof(ICollection) || t == typeof(IList))
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
if (t.IsGenericType)
{
var genericTypeDefinition = t.GetGenericTypeDefinition();
var arrayItemType = t.GetGenericArguments()[0];
if (genericTypeDefinition == typeof(IEnumerable<>) || genericTypeDefinition == typeof(IList<>) || genericTypeDefinition == typeof(ICollection<>) || genericTypeDefinition == typeof(ISet<>)
#if !Net4
|| genericTypeDefinition == typeof(IReadOnlyList<>) || genericTypeDefinition == typeof(IReadOnlyCollection<>)
#endif
)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
}
return null;
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsCollectionType(Type t)
{
if (t.IsInterface)
return null;
var intserfaces = t.GetInterfaces();
bool hasIEnumerableGeneric = false;
bool hasICollectionGeneric = false;
bool hasIListGeneric = false;
bool hasICollection = false;
bool hasIList = false;
Type arrayItemType = null;
Type iCollectionGenericType = null;
Type iEnumerableGenericType = null;
Type iListGenericType = null;
foreach (var item in intserfaces)
{
if (item.IsGenericType)
{
var genericTypeDefinition = item.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IEnumerable<>))
{
hasIEnumerableGeneric = true;
arrayItemType = item.GetGenericArguments()[0];
iEnumerableGenericType = item;
}
else if (genericTypeDefinition == typeof(ICollection<>))
{
hasICollectionGeneric = true;
arrayItemType = item.GetGenericArguments()[0];
iCollectionGenericType = item;
}
else if (genericTypeDefinition == typeof(IList<>))
{
hasIListGeneric = true;
arrayItemType = item.GetGenericArguments()[0];
iListGenericType = item;
}
}
else if (item == typeof(ICollection))
hasICollection = true;
else if (item == typeof(IList))
hasIList = true;
}
if (hasIListGeneric)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iListGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IListGeneric);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IListGeneric);
}
else
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IListGeneric);
}
if (hasICollectionGeneric)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iCollectionGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
else
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
if (hasIEnumerableGeneric && hasICollection)
{
var ctor = t.GetAppointTypeCtor(iEnumerableGenericType);
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
}
}
}
else
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.IEnumerableGeneric);
}
if (hasIList)
{
var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IList));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
}
}
}
else if (ctor.GetParameters().Length == 0)
{
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
else
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
if (hasICollection)
{
var ctor = t.GetAppointTypeCtor(typeof(ICollection));
if (ctor == null)
{
foreach (var item in t.GetConstructors())
{
if (item.GetParameters().Length == 1)
{
var firstCtor = item.GetParameters()[0];
if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null)
{
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
}
}
}
else
return () => (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
return null;
}
private static Func<Action<T, JsonSerializerHandler>> TypeIsSpecial(Type t)
{
if (t.IsGenericType)
{
var genericTypeDefinition = t.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(KeyValuePair<,>))
{
var keyType = t.GetGenericArguments()[0];
return () => IsWrongKeyType(keyType) ?? BuildFactory.Create<T>(SerializerBuildTypeEnum.KeyValuePair);
}
if (genericTypeDefinition == typeof(Nullable<>))
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.Nullable);
if (genericTypeDefinition == typeof(Lazy<>))
return () => BuildFactory.Create<T>(SerializerBuildTypeEnum.Lazy);
if (genericTypeDefinition == typeof(Lookup<,>))
{
}
if (genericTypeDefinition == typeof(ILookup<,>))
{
}
}
return null;
}
private static Action<T, JsonSerializerHandler> IsArray(Type t)
{
if (t.IsArray)
{
if (t.GetArrayRank() == 1)
return BuildFactory.Create<T>(SerializerBuildTypeEnum.IListGeneric);
else
return (obj, handler) => SpecialConditions.WriteCollection((IEnumerable)obj, handler);
}
return null;
}
private static Action<T, JsonSerializerHandler> IsLoadDynamic(Type t)
{
if (t.IsAnonymousType())
return (a, b) => SpecialConditions.WriteDynamic(a, b);
return null;
}
private static Action<T, JsonSerializerHandler> IsEnum(Type t)
{
if (t.IsEnum)
return GenerateLambdaCallWithTypeConvert(SpecialConditions._WriteEnum, typeof(Enum));
return null;
}
private static Action<T, JsonSerializerHandler> IsWrongKeyType(Type keyType)
{
if (keyType.IsWrongKey())
return BuildFactory.Create<T>(SerializerBuildTypeEnum.WrongGenericKey);
return null;
}
private static Action<T, JsonSerializerHandler> GenerateLambdaCall(MethodInfo method)
{
ParameterExpression objArg = Expression.Parameter(typeof(T), "instance");
ParameterExpression handlerArg = Expression.Parameter(typeof(JsonSerializerHandler), "handler");
var body = Expression.Call(method, objArg, handlerArg);
return Expression.Lambda<Action<T, JsonSerializerHandler>>(body, objArg, handlerArg).Compile();
}
private static Action<T, JsonSerializerHandler> GenerateLambdaCallWithTypeConvert(MethodInfo method, Type t)
{
ParameterExpression objArg = Expression.Parameter(typeof(T), "instance");
ParameterExpression handlerArg = Expression.Parameter(typeof(JsonSerializerHandler), "handler");
var body = Expression.Call(method, Expression.Convert(objArg, t), handlerArg);
return Expression.Lambda<Action<T, JsonSerializerHandler>>(body, objArg, handlerArg).Compile();
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Runtime.CompilerServices;
namespace CPF.Json.Serializer
{
internal class FormattingProvider<T>
{
internal static Action<T, JsonSerializerHandler> Get = FormatterFind<T>.Find();
#if !Net4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
internal static void Convert(T type, JsonSerializerHandler handler) => Get(type, handler);
}
}

View File

@ -0,0 +1,7 @@

namespace CPF.Json.Serializer
{
internal class JsonFormatterBase
{
}
}

Some files were not shown because too many files have changed in this diff Show More