static Converter() { TypeInfo typeInfo = typeof(T).GetTypeInfo(); _isValueType = typeInfo.IsValueType; _readFieldActions = new Dictionary <string, ReadFieldAction>(); _writeAction = (in T v, StreamWriter w, int _) => w.WriteLine(v.ToString()); #region clr types if (typeof(T) == typeof(bool)) { _readAction = Converter.ConvertRead <T>(Converter <bool> .GetReadAction(bool.Parse)); } else if (typeof(T) == typeof(sbyte)) { _readAction = Converter.ConvertRead <T>(Converter <sbyte> .GetReadAction(sbyte.Parse)); } else if (typeof(T) == typeof(byte)) { _readAction = Converter.ConvertRead <T>(Converter <byte> .GetReadAction(byte.Parse)); } else if (typeof(T) == typeof(short)) { _readAction = Converter.ConvertRead <T>(Converter <short> .GetReadAction(short.Parse)); } else if (typeof(T) == typeof(ushort)) { _readAction = Converter.ConvertRead <T>(Converter <ushort> .GetReadAction(ushort.Parse)); } else if (typeof(T) == typeof(int)) { _readAction = Converter.ConvertRead <T>(Converter <int> .GetReadAction(int.Parse)); } else if (typeof(T) == typeof(uint)) { _readAction = Converter.ConvertRead <T>(Converter <uint> .GetReadAction(uint.Parse)); } else if (typeof(T) == typeof(long)) { _readAction = Converter.ConvertRead <T>(Converter <long> .GetReadAction(long.Parse)); } else if (typeof(T) == typeof(ulong)) { _readAction = Converter.ConvertRead <T>(Converter <ulong> .GetReadAction(ulong.Parse)); } else if (typeof(T) == typeof(char)) { _readAction = Converter.ConvertRead <T>(Converter <char> .GetReadAction(CharParse)); } else if (typeof(T) == typeof(decimal)) { _readAction = Converter.ConvertRead <T>(Converter <decimal> .GetReadAction(decimal.Parse)); } else if (typeof(T) == typeof(double)) { _readAction = Converter.ConvertRead <T>(Converter <double> .GetReadAction(double.Parse)); } else if (typeof(T) == typeof(float)) { _readAction = Converter.ConvertRead <T>(Converter <float> .GetReadAction(float.Parse)); } else if (typeof(T) == typeof(string)) { _readAction = Converter.ConvertRead <T>(Converter <string> .GetReadAction(s => s)); } else if (typeInfo.IsEnum) { ParameterExpression line = Expression.Parameter(typeof(string)); ParameterExpression reader = Expression.Parameter(typeof(StreamReader)); Expression readIfNull = Expression.Condition( Expression.Equal(line, Expression.Constant(null, typeof(string))), Expression.Call(reader, typeof(StreamReader).GetTypeInfo().GetDeclaredMethod(nameof(StreamReader.ReadLine))), line); _readAction = Expression.Lambda <Converter.ReadAction <T> >(Expression.Call(typeof(Converter <T>).GetTypeInfo().GetDeclaredMethod(nameof(ReadEnum)).MakeGenericMethod(typeof(T)), readIfNull), line, reader).Compile(); } else if (typeInfo.IsArray) { Type elementType = typeInfo.GetElementType(); _writeAction = (Converter.WriteAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(WriteArray)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(ReadArray)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else #endregion { #region Filters bool Parameters_string(MethodInfo methodInfo) { ParameterInfo[] parameters = methodInfo.GetParameters(); return(parameters.Length == 1 && parameters[0].ParameterType == typeof(string)); } bool Parameters_string_string(MethodInfo methodInfo) { ParameterInfo[] parameters = methodInfo.GetParameters(); return(parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string)); } #endregion MethodInfo write = typeof(StreamWriter).GetTypeInfo().GetDeclaredMethods(nameof(StreamWriter.Write)).First(Parameters_string); MethodInfo writeLineString = typeof(Converter <T>).GetTypeInfo().GetDeclaredMethod(nameof(StreamWriterWriteLine)); MethodInfo stringConcat = typeof(string).GetTypeInfo().GetDeclaredMethods(nameof(string.Concat)).First(Parameters_string_string); ParameterExpression value = Expression.Parameter(typeof(T).MakeByRefType()); ParameterExpression writer = Expression.Parameter(typeof(StreamWriter)); ParameterExpression indentation = Expression.Parameter(typeof(int)); ParameterExpression space = Expression.Variable(typeof(string)); Expression assignSpace = Expression.Assign(space, Expression.Call(typeof(Converter <T>).GetTypeInfo().GetDeclaredMethod(nameof(CreateIndentation)), indentation)); List <Expression> writeExpressions = new List <Expression> { Expression.Call(writeLineString, writer, Expression.Constant(_objectBegin)), Expression.PreIncrementAssign(indentation), assignSpace }; while (typeInfo != null) { foreach (FieldInfo fieldInfo in typeInfo.DeclaredFields.Where(f => !f.IsStatic)) { string name = GetFriendlyName(fieldInfo.Name); Expression writeField = Expression.Block( Expression.Call(writer, write, Expression.Call(stringConcat, space, Expression.Constant(name))), Expression.Call(writer, write, Expression.Constant(" ")), Expression.Call( typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Write)), Expression.Field(value, fieldInfo), writer, indentation)); writeExpressions.Add(writeField); DynamicMethod readMethod = new DynamicMethod($"Set_{nameof(T)}_{fieldInfo.Name}", typeof(void), new[] { typeof(string), typeof(StreamReader), typeof(T).MakeByRefType() }, typeof(Converter <T>), true); ILGenerator readGenerator = readMethod.GetILGenerator(); readGenerator.Emit(OpCodes.Ldarg_2); if (!typeInfo.IsValueType) { readGenerator.Emit(OpCodes.Ldind_Ref); } readGenerator.Emit(OpCodes.Ldarg_0); readGenerator.Emit(OpCodes.Ldarg_1); readGenerator.Emit(OpCodes.Call, typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Converter <T> .Read))); readGenerator.Emit(OpCodes.Stfld, fieldInfo); readGenerator.Emit(OpCodes.Ret); _readFieldActions.Add(name.ToUpperInvariant(), (ReadFieldAction)readMethod.CreateDelegate(typeof(ReadFieldAction))); } typeInfo = typeInfo.BaseType?.GetTypeInfo(); } writeExpressions.Add(Expression.PreDecrementAssign(indentation)); writeExpressions.Add(assignSpace); writeExpressions.Add(Expression.Call(writeLineString, writer, Expression.Call(stringConcat, space, Expression.Constant(_objectEnd)))); _writeAction = Expression.Lambda <Converter.WriteAction <T> >(Expression.Block(new[] { space }, writeExpressions), value, writer, indentation).Compile(); _readAction = ReadAnyType; } }
static Converter() { TypeInfo typeInfo = typeof(T).GetTypeInfo(); _isValueType = typeInfo.IsValueType; _readFieldActions = new Dictionary <string, ReadFieldAction>(); _writeAction = (in T v, StreamWriter w, int _) => w.WriteLine(v.ToString()); #region clr types if (typeof(T) == typeof(bool)) { _readAction = Converter.ConvertRead <T>(Converter <bool> .GetReadAction(bool.Parse)); } else if (typeof(T) == typeof(sbyte)) { _readAction = Converter.ConvertRead <T>(Converter <sbyte> .GetReadAction(sbyte.Parse)); } else if (typeof(T) == typeof(byte)) { _readAction = Converter.ConvertRead <T>(Converter <byte> .GetReadAction(byte.Parse)); } else if (typeof(T) == typeof(short)) { _readAction = Converter.ConvertRead <T>(Converter <short> .GetReadAction(short.Parse)); } else if (typeof(T) == typeof(ushort)) { _readAction = Converter.ConvertRead <T>(Converter <ushort> .GetReadAction(ushort.Parse)); } else if (typeof(T) == typeof(int)) { _readAction = Converter.ConvertRead <T>(Converter <int> .GetReadAction(int.Parse)); } else if (typeof(T) == typeof(uint)) { _readAction = Converter.ConvertRead <T>(Converter <uint> .GetReadAction(uint.Parse)); } else if (typeof(T) == typeof(long)) { _readAction = Converter.ConvertRead <T>(Converter <long> .GetReadAction(long.Parse)); } else if (typeof(T) == typeof(ulong)) { _readAction = Converter.ConvertRead <T>(Converter <ulong> .GetReadAction(ulong.Parse)); } else if (typeof(T) == typeof(char)) { _readAction = Converter.ConvertRead <T>(Converter <char> .GetReadAction(CharParse)); } else if (typeof(T) == typeof(decimal)) { _readAction = Converter.ConvertRead <T>(Converter <decimal> .GetReadAction(decimal.Parse)); } else if (typeof(T) == typeof(double)) { _readAction = Converter.ConvertRead <T>(Converter <double> .GetReadAction(double.Parse)); } else if (typeof(T) == typeof(float)) { _readAction = Converter.ConvertRead <T>(Converter <float> .GetReadAction(float.Parse)); } else if (typeof(T) == typeof(string)) { _readAction = Converter.ConvertRead <T>(Converter <string> .GetReadAction(s => s)); } else if (typeInfo.IsEnum) { ParameterExpression line = Expression.Parameter(typeof(string)); ParameterExpression reader = Expression.Parameter(typeof(StreamReader)); Expression readIfNull = Expression.Condition( Expression.Equal(line, Expression.Constant(null, typeof(string))), Expression.Call(reader, typeof(StreamReader).GetTypeInfo().GetDeclaredMethod(nameof(StreamReader.ReadLine))), line); _readAction = Expression.Lambda <Converter.ReadAction <T> >(Expression.Call(typeof(Converter <T>).GetTypeInfo().GetDeclaredMethod(nameof(ReadEnum)).MakeGenericMethod(typeof(T)), readIfNull), line, reader).Compile(); } else if (typeInfo.IsArray) { Type elementType = typeInfo.GetElementType(); _writeAction = (Converter.WriteAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(WriteArray)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(ReadArray)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else #endregion {
static Converter() { _type = typeof(T); TypeInfo typeInfo = _type.GetTypeInfo(); if (_type == typeof(string)) { _writeAction = (Converter.WriteAction <T>)(Delegate) new Converter.WriteAction <string>(StringConverter.Write); _readAction = (Converter.ReadAction <T>)(Delegate) new Converter.ReadAction <string>(StringConverter.Read); } else if (typeInfo.IsArray) { Type elementType = typeInfo.GetElementType(); _writeAction = (Converter.WriteAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(WriteArray)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(ReadArray)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else { try { if (typeInfo.IsUnmanaged()) { TypeInfo unmanagedType = typeof(UnmanagedConverter <>).MakeGenericType(_type).GetTypeInfo(); _writeAction = (Converter.WriteAction <T>)unmanagedType.GetDeclaredMethod(nameof(UnmanagedConverter <bool> .Write)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>)unmanagedType.GetDeclaredMethod(nameof(UnmanagedConverter <bool> .Read)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else { DynamicMethod writeMethod = new DynamicMethod($"Write_{nameof(T)}", typeof(void), new[] { _type.MakeByRefType(), typeof(Stream), typeof(byte[]), typeof(byte *) }, typeof(Converter <T>), true); ILGenerator writeGenerator = writeMethod.GetILGenerator(); DynamicMethod readMethod = new DynamicMethod($"Read_{nameof(T)}", _type, new[] { typeof(Stream), typeof(byte[]), typeof(byte *) }, typeof(Converter <T>), true); ILGenerator readGenerator = readMethod.GetILGenerator(); LocalBuilder readValue = readGenerator.DeclareLocal(_type); if (typeInfo.IsClass) { readGenerator.Emit(OpCodes.Ldsfld, typeof(Converter <T>).GetTypeInfo().GetDeclaredField(nameof(_type))); readGenerator.Emit(OpCodes.Call, typeof(ObjectInitializer).GetTypeInfo().GetDeclaredMethod(nameof(ObjectInitializer.Create))); readGenerator.Emit(OpCodes.Stloc, readValue); } else { readGenerator.Emit(OpCodes.Ldloca_S, readValue); readGenerator.Emit(OpCodes.Initobj, _type); } while (typeInfo != null) { foreach (FieldInfo fieldInfo in typeInfo.DeclaredFields.Where(f => !f.IsStatic)) { writeGenerator.Emit(OpCodes.Ldarg_0); if (typeInfo.IsClass) { writeGenerator.Emit(OpCodes.Ldind_Ref); } writeGenerator.Emit(OpCodes.Ldflda, fieldInfo); writeGenerator.Emit(OpCodes.Ldarg_1); writeGenerator.Emit(OpCodes.Ldarg_2); writeGenerator.Emit(OpCodes.Ldarg_3); writeGenerator.Emit(OpCodes.Call, typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Converter <T> .Write))); readGenerator.Emit(typeInfo.IsClass ? OpCodes.Ldloc : OpCodes.Ldloca_S, readValue); readGenerator.Emit(OpCodes.Ldarg_0); readGenerator.Emit(OpCodes.Ldarg_1); readGenerator.Emit(OpCodes.Ldarg_2); readGenerator.Emit(OpCodes.Call, typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Converter <T> .Read))); readGenerator.Emit(OpCodes.Stfld, fieldInfo); } typeInfo = typeInfo.BaseType?.GetTypeInfo(); } writeGenerator.Emit(OpCodes.Ret); _writeAction = (Converter.WriteAction <T>)writeMethod.CreateDelegate(typeof(Converter.WriteAction <T>)); readGenerator.Emit(OpCodes.Ldloc, readValue); readGenerator.Emit(OpCodes.Ret); _readAction = (Converter.ReadAction <T>)readMethod.CreateDelegate(typeof(Converter.ReadAction <T>)); } } catch { _writeAction = (in T _, Stream __, byte[] ___, byte *____) => throw new InvalidOperationException($"Unable to handle type {_type.FullName}"); _readAction = (_, __, ___) => throw new InvalidOperationException($"Unable to handle type {_type.FullName}"); } } }