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; } }); }
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))); } }
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; } }); }