private Func <object, Value> BuildProtoConverter()
        {
            // Create reusable JsonSerializer to reduce allocations
            var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings()
            {
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            };

            jsonSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
            var jsonSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(jsonSettings);

            return(o => {
                try
                {
                    switch (Convert.GetTypeCode(o))
                    {
                    case TypeCode.Empty:
                        return Value.ForNull();

                    case TypeCode.Boolean:
                        return Value.ForBool((bool)o);

                    case TypeCode.Decimal:
                    case TypeCode.Double:
                    case TypeCode.Single:
                        return Value.ForNumber(Convert.ToDouble(o));

                    case TypeCode.Byte:
                    case TypeCode.SByte:
                    case TypeCode.Int16:
                    case TypeCode.UInt16:
                    case TypeCode.Int32:
                    case TypeCode.UInt32:
                    case TypeCode.Int64:
                    case TypeCode.UInt64:
                        if (o is System.Enum)
                        {
                            break;      // Let StringEnumConverter handle formatting
                        }
                        return Value.ForNumber(Convert.ToDouble(o));

                    case TypeCode.String:
                        return Value.ForString((string)o);

                    case TypeCode.Char:
                        return Value.ForString(o.ToString());
                    }
                    return ProtoConverter.Convert(JToken.FromObject(o, jsonSerializer));
                }
                catch
                {
                    // Reset the JsonSerializer as it now can be in a bad state
                    jsonSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(jsonSettings);
                    throw;
                }
            });
        }
예제 #2
0
        private Func <object, Value> BuildAndVerifyJsonConverter()
        {
            var type = System.Type.GetType(JsonConverterTypeName, throwOnError: false);

            GaxPreconditions.CheckState(type != null, "A type with the specified name cannot be found: '{0}'", JsonConverterTypeName);
            var methodInfo = type.GetTypeInfo()
                             .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)
                             .Where(m => m.Name == JsonConverterMethodName && !m.IsAbstract && !m.IsGenericMethod &&
                                    m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(object) &&
                                    (m.ReturnType == typeof(Value) || typeof(JToken).IsAssignableFrom(m.ReturnType)))
                             .FirstOrDefault();

            GaxPreconditions.CheckState(methodInfo != null,
                                        $"A suitable public method named '{JsonConverterMethodName}' cannot be found in type '{JsonConverterTypeName}'. " +
                                        "The public method must have a single parameter of type 'object', and a return type of 'Value' or 'JToken'");
            object instance = null;

            if (!methodInfo.IsStatic)
            {
                try
                {
                    instance = Activator.CreateInstance(type);
                }
                catch (Exception e)
                {
                    // Acticator.CreateInstance can throw many different exceptions, so catch them all.
                    throw new InvalidOperationException(
                              $"Type '{JsonConverterTypeName}' must have a parameterless constructor so it can be instantiated.", e);
                }
            }
            if (methodInfo.ReturnType == typeof(Value))
            {
                return((Func <object, Value>)methodInfo.CreateDelegate(typeof(Func <object, Value>), instance));
            }
            else
            {
                var fn = (Func <object, JToken>)methodInfo.CreateDelegate(typeof(Func <object, JToken>), instance);
                return(o => ProtoConverter.Convert(fn(o)));
            }
        }
예제 #3
0
        private Func <object, Value> BuildProtoConverter()
        {
            // Create reusable JsonSerializer to reduce allocations
            var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings()
            {
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            };

            jsonSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
            // The default serialization of these reflection types really isn't useful, so
            // just call ToString on them instead.
            jsonSettings.Converters.Add(new ToStringJsonConverter(typeof(MemberInfo)));
            jsonSettings.Converters.Add(new ToStringJsonConverter(typeof(Assembly)));
            jsonSettings.Converters.Add(new ToStringJsonConverter(typeof(Module)));
            jsonSettings.Converters.Add(new ToStringJsonConverter(typeof(System.IO.Stream)));

            jsonSettings.Error = (sender, args) =>
            {
                // Serialization of properties that throws exceptions should not break everything
                InternalLogger.Debug(args.ErrorContext.Error, "GoogleStackdriver(Name={0}): Error serializing exception property: {1}", Name, args.ErrorContext.Member);
                args.ErrorContext.Handled = true;
            };
            var jsonSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(jsonSettings);

            return(o => {
                try
                {
                    switch (Convert.GetTypeCode(o))
                    {
                    case TypeCode.Empty:
                        return Value.ForNull();

                    case TypeCode.Boolean:
                        return Value.ForBool(Convert.ToBoolean(o));

                    case TypeCode.Decimal:
                    case TypeCode.Double:
                    case TypeCode.Single:
                        return Value.ForNumber(Convert.ToDouble(o));

                    case TypeCode.Byte:
                    case TypeCode.SByte:
                    case TypeCode.Int16:
                    case TypeCode.UInt16:
                    case TypeCode.Int32:
                    case TypeCode.UInt32:
                    case TypeCode.Int64:
                    case TypeCode.UInt64:
                        if (o is System.Enum)
                        {
                            break;      // Let StringEnumConverter handle formatting
                        }
                        return Value.ForNumber(Convert.ToDouble(o));

                    case TypeCode.String:
                    case TypeCode.Char:
                        return Value.ForString(o.ToString());
                    }
                    return ProtoConverter.Convert(JToken.FromObject(o, jsonSerializer));
                }
                catch
                {
                    // Reset the JsonSerializer as it now can be in a bad state
                    jsonSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(jsonSettings);
                    throw;
                }
            });
        }