284 lines
10 KiB
C#
284 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace CPF.Windows.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
|
|
|
|
}
|
|
}
|