Ejemplo n.º 1
0
 private object Deserialize(Type type, TFormat value)
 {
     if (value == null)
     {
         return(null);
     }
     return(DeserializationMethod.MakeGenericMethod(type).Invoke(Serializer, new object[] { value, default(StreamingContext) }));
 }
Ejemplo n.º 2
0
            private static DeserializationHandler <T> CreateDeserializationHandler()
            {
                var constructor = typeof(T).GetConstructors().Single();

                // Generate a "TBuilder" type implementing IBuilder<T>.
                // We'll trick the JSON serializer into deserializing a "TBuilder" then instanciate the final object by calling IBuilder<T>.Build().
                // Not the cleanest way to do it, but might be one of the less "allocatey" ?
                string assemblyName    = $"Serialization.Json.Builders.{typeof(T).Name}";
                var    assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.RunAndCollect);
                var    moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName);
                var    typeBuilder     = moduleBuilder.DefineType(assemblyName + "Builder", TypeAttributes.Public | TypeAttributes.Sealed, typeof(ValueType));
                var    properties      = Array.ConvertAll
                                         (
                    constructor.GetParameters(),
                    parameter =>
                {
                    string propertyName = char.ToUpperInvariant(parameter.Name[0]) + parameter.Name.Substring(1);
                    // Fields ought to be enough, but System.Text.Json seems to require properties 😥
                    var field = typeBuilder.DefineField($"_{parameter.Name}", parameter.ParameterType, FieldAttributes.Public);

                    var getMethodBuilder = typeBuilder.DefineMethod($"get_{propertyName}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, parameter.ParameterType, Type.EmptyTypes);
                    {
                        var ilGenerator = getMethodBuilder.GetILGenerator();

                        ilGenerator.Emit(OpCodes.Ldarg_0);
                        ilGenerator.Emit(OpCodes.Ldfld, field);
                        ilGenerator.Emit(OpCodes.Ret);
                    }

                    var setMethodBuilder = typeBuilder.DefineMethod($"set_{propertyName}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, typeof(void), new[] { parameter.ParameterType });
                    {
                        var ilGenerator = setMethodBuilder.GetILGenerator();

                        ilGenerator.Emit(OpCodes.Ldarg_0);
                        ilGenerator.Emit(OpCodes.Ldarg_1);
                        ilGenerator.Emit(OpCodes.Stfld, field);
                        ilGenerator.Emit(OpCodes.Ret);
                    }

                    var property = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, parameter.ParameterType, Type.EmptyTypes);
                    property.SetGetMethod(getMethodBuilder);
                    property.SetSetMethod(setMethodBuilder);

                    return(property);
                }
                                         );

                var methodBuilder = typeBuilder.DefineMethod("Build", MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final, CallingConventions.HasThis, typeof(T), Type.EmptyTypes);

                {
                    var ilGenerator = methodBuilder.GetILGenerator();
                    foreach (var property in properties)
                    {
                        ilGenerator.Emit(OpCodes.Ldarg_0);
                        ilGenerator.Emit(OpCodes.Call, property.GetMethod);
                    }
                    ilGenerator.Emit(OpCodes.Newobj, constructor);
                    ilGenerator.Emit(OpCodes.Ret);
                }
                typeBuilder.AddInterfaceImplementation(typeof(IBuilder <T>));

                var builderType = typeBuilder.CreateTypeInfo();

                return((DeserializationHandler <T>)DeserializationMethod.MakeGenericMethod(new[] { typeof(T), builderType })
                       .CreateDelegate(typeof(DeserializationHandler <T>), ImmutableJsonConverter.Instance));
            }