Beispiel #1
0
        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;
            }
        }
Beispiel #2
0
        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
            {
Beispiel #3
0
        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}");
                }
            }
        }