Ejemplo n.º 1
0
        public void EmittedAppendToStringBuilderIsValid(Type emitterType, Type valueType, object testValue, string expectedResult)
        {
            if (valueType == typeof(decimal))
            {
                testValue = (decimal)(double)testValue;
            }
            else if (valueType == typeof(decimal?))
            {
                testValue = (decimal?)(double?)testValue;
            }
            IConverterEmitter emitter        = (IConverterEmitter)Activator.CreateInstance(emitterType) !;
            DynamicMethod     serialize      = new DynamicMethod("Serialize", typeof(string), new Type[] { valueType, typeof(IFormatProvider), typeof(char) }, typeof(NumberConverterTests));
            LocalBuilder?     local          = null;
            LocalBuilder?     secondaryLocal = null;

            serialize.GetILGenerator()
            .Emit(gen => {
                if (valueType == typeof(float) || valueType == typeof(double) || valueType == typeof(decimal))
                {
                    gen.DeclareLocal(valueType, out local);
                }
                else if (Nullable.GetUnderlyingType(valueType) is Type underlyingType)
                {
                    if (underlyingType == typeof(float) || underlyingType == typeof(double) || underlyingType == typeof(decimal))
                    {
                        gen.DeclareLocal(typeof(Nullable <>).MakeGenericType(underlyingType), out local);
                        gen.DeclareLocal(valueType, out secondaryLocal);
                    }
                    else
                    {
                        gen.DeclareLocal(typeof(Nullable <>).MakeGenericType(underlyingType), out local);
                    }
                }
            })
            .Newobj <StringBuilder>()
            .Ldarg_0()
            .Emit(gen => emitter.EmitAppendToStringBuilder(gen, local, secondaryLocal, null))
            .Callvirt <StringBuilder>("ToString")
            .Ret();
            string serialized = (string)serialize.Invoke(null, new[] { testValue, CultureInfo.InvariantCulture, ',' }) !;

            serialized.Should().Be(expectedResult);
        }
Ejemplo n.º 2
0
        private static void DefineSerializeItem <T>(ILGenerator gen)
        {
            PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            Dictionary <Type, LocalBuilder> localByType = new Dictionary <Type, LocalBuilder>();

            gen
            .Ldarg_3()
            .Emit(gen => {
                bool firstProperty = true;
                foreach (PropertyInfo property in properties)
                {
                    if (!property.CanRead)
                    {
                        throw new CsvTypeException(typeof(T), property.Name, "Property doesn't have a public getter.");
                    }
                    CsvColumnAttribute?columnAttribute = property.GetCustomAttribute <CsvColumnAttribute>();
                    gen
                    .Emit(gen => firstProperty switch {
                        false => gen
                        .Ldarg_2()
                        .Callvirt <StringBuilder>("Append", typeof(char)),
                        _ => gen
                    })
                    .Emit(gen => gen
                          .Ldarg(4)
                          .Callvirt(property.GetGetMethod() !)
                          .Emit(gen => {
                        IConverterEmitter converterEmitter = ConverterFactory.GetOrCreateEmitter(property.PropertyType);
                        ConverterEmitterAttribute converterEmitterAttribute = converterEmitter.GetType().GetMethod("EmitAppendToStringBuilder") !.GetCustomAttribute <ConverterEmitterAttribute>() !;
                        LocalBuilder?local          = null;
                        LocalBuilder?secondaryLocal = null;
                        if (converterEmitterAttribute.NullableOfGenericParameterIsPrimaryLocalType && converterEmitter.GetType().IsGenericType)
                        {
                            Type genericParameter = converterEmitter.GetType().GetGenericArguments()[0];
                            Type localType        = typeof(Nullable <>).MakeGenericType(genericParameter);
                            if (!localByType.TryGetValue(localType, out local))
                            {
                                local = gen.DeclareLocal(localType);
                                localByType.Add(localType, local);
                            }
                        }
                        else if (converterEmitterAttribute.GenericParameterIsPrimaryLocalType && converterEmitter.GetType().IsGenericType)
                        {
                            Type localType = converterEmitter.GetType().GetGenericArguments()[0];
                            if (!localByType.TryGetValue(localType, out local))
                            {
                                local = gen.DeclareLocal(localType);
                                localByType.Add(localType, local);
                            }
                        }
                        else if (converterEmitterAttribute.PrimaryLocalType is Type localType)
                        {
                            if (!localByType.TryGetValue(localType, out local))
                            {
                                local = gen.DeclareLocal(localType);
                                localByType.Add(localType, local);
                            }
                        }
                        if (converterEmitterAttribute.SecondaryLocalType is Type secondaryLocalType)
                        {
                            if (!localByType.TryGetValue(secondaryLocalType, out secondaryLocal))
                            {
                                secondaryLocal = gen.DeclareLocal(secondaryLocalType);
                                localByType.Add(secondaryLocalType, secondaryLocal);
                            }
                        }
                        converterEmitter.EmitAppendToStringBuilder(gen, local, secondaryLocal, columnAttribute);
                    })
                          );
                    firstProperty = false;
                }