public static object ConvertToClrType(this Value wireValue, V1.Type spannerType, System.Type targetClrType) { if (wireValue.KindCase == Value.KindOneofCase.NullValue) { if (targetClrType.GetTypeInfo().IsValueType) { //Returns default(T) for targetClrType return(Activator.CreateInstance(targetClrType)); } return(null); } if (targetClrType == typeof(object)) { //then we decide the type for you targetClrType = spannerType?.Code.GetDefaultClrTypeFromSpannerType(); } var possibleUnderlyingType = Nullable.GetUnderlyingType(targetClrType); if (possibleUnderlyingType != null) { targetClrType = possibleUnderlyingType; } //extra supported conversions that are modifications of the "core" versions but may have loss of precision. //we call the spannerType with the known supported version and cast it down to lose precision. if (targetClrType == typeof(int)) { return(Convert.ToInt32((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(uint)) { return(Convert.ToUInt32((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(short)) { return(Convert.ToInt16((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(ushort)) { return(Convert.ToUInt16((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(char)) { return(Convert.ToChar((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(byte)) { return(Convert.ToByte((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(long)))); } if (targetClrType == typeof(decimal)) { return(Convert.ToDecimal((long)ConvertToClrTypeImpl(wireValue, spannerType, typeof(decimal)))); } if (targetClrType == typeof(float)) { return(Convert.ToSingle((double)ConvertToClrTypeImpl(wireValue, spannerType, typeof(double)))); } if (targetClrType == typeof(Guid)) { return(Guid.Parse((string)ConvertToClrTypeImpl(wireValue, spannerType, typeof(string)))); } return(ConvertToClrTypeImpl(wireValue, spannerType, targetClrType)); }
public static T ConvertToClrType <T>( this Value wireValue, V1.Type spannerType) => (T)ConvertToClrType(wireValue, spannerType, typeof(T));
private static object ConvertToClrTypeImpl(Value wireValue, V1.Type spannerType, System.Type targetClrType) { //If the wireValue itself is assignable to the target type, just return it //This covers both typeof(Value) and typeof(object). if (wireValue == null || targetClrType == null || targetClrType == typeof(Value)) { return(wireValue); } //targetClrType should be one of the values returned by GetDefaultClrTypeFromSpannerType if (targetClrType == typeof(bool)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(default(bool)); case Value.KindOneofCase.StringValue: return(Convert.ToBoolean(wireValue.StringValue)); case Value.KindOneofCase.BoolValue: return(wireValue.BoolValue); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(long)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NumberValue: return(Convert.ToInt64(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(long)); case Value.KindOneofCase.StringValue: return(Convert.ToInt64(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(double)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(default(double)); case Value.KindOneofCase.NumberValue: return(wireValue.NumberValue); case Value.KindOneofCase.StringValue: if (string.Compare(wireValue.StringValue, "NaN", StringComparison.OrdinalIgnoreCase) == 0) { return(double.NaN); } if (string.Compare(wireValue.StringValue, "Infinity", StringComparison.OrdinalIgnoreCase) == 0) { return(double.PositiveInfinity); } if (string.Compare(wireValue.StringValue, "-Infinity", StringComparison.OrdinalIgnoreCase) == 0) { return(double.NegativeInfinity); } return(Convert.ToDouble(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(DateTime)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.StringValue: return(XmlConvert.ToDateTime(wireValue.StringValue, XmlDateTimeSerializationMode.Utc)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(Timestamp)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.StringValue: return(Timestamp.Parser.ParseJson(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(string)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.NumberValue: return(wireValue.NumberValue.ToString(CultureInfo.CurrentCulture)); case Value.KindOneofCase.StringValue: return(wireValue.StringValue); case Value.KindOneofCase.BoolValue: return(wireValue.BoolValue.ToString()); default: return(wireValue.ToString()); } } if (targetClrType == typeof(byte[])) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.StringValue: return(Convert.FromBase64String(wireValue.StringValue)); default: throw new ArgumentOutOfRangeException(); } } if (typeof(IDictionary).IsAssignableFrom(targetClrType)) { if (targetClrType == typeof(IDictionary)) { targetClrType = typeof(Hashtable); } //a bit of recursion here... IDictionary dictionary = (IDictionary)Activator.CreateInstance(targetClrType); switch (wireValue.KindCase) { case Value.KindOneofCase.StructValue: foreach (var structField in spannerType.StructType.Fields) { dictionary[structField.Name] = wireValue.StructValue.Fields[structField.Name] .ConvertToClrType(structField.Type); } return(dictionary); case Value.KindOneofCase.ListValue: if (spannerType.Code == TypeCode.Struct) { for (var i = 0; i < spannerType.StructType.Fields.Count; i++) { dictionary[spannerType.StructType.Fields[i].Name] = wireValue .ListValue.Values[i] .ConvertToClrType(spannerType.StructType.Fields[i].Type); } } else { var i = 0; foreach (var listItemValue in wireValue.ListValue.Values) { dictionary[i] = listItemValue.ConvertToClrType(spannerType.ArrayElementType); i++; } } return(dictionary); default: throw new ArgumentException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType.IsArray) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.ListValue: var newArray = Array.CreateInstance( targetClrType.GetElementType(), wireValue.ListValue.Values.Count); var i = 0; foreach (var obj in wireValue.ListValue.Values.Select( x => x.ConvertToClrType(spannerType.ArrayElementType, targetClrType.GetElementType()))) { newArray.SetValue(obj, i); i++; } return(newArray); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (typeof(IList).IsAssignableFrom(targetClrType)) { if (targetClrType == typeof(IList)) { targetClrType = typeof(ArrayList); } switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.ListValue: var newList = (IList)Activator.CreateInstance(targetClrType); foreach (var obj in wireValue.ListValue.Values.Select( x => x.ConvertToClrType(spannerType.ArrayElementType))) { newList.Add(obj); } return(newList); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } throw new ArgumentException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); }
public static object ConvertToClrType(this Value wireValue, V1.Type spannerType) => ConvertToClrType( wireValue, spannerType, typeof(object));
private static T ConvertToClrTypeImpl <T>(Value wireValue, V1.Type spannerType) => (T)ConvertToClrTypeImpl(wireValue, spannerType, typeof(T));