public override int GetHashCode() { int hash = 1; if (Code != global::Google.Cloud.Spanner.V1.TypeCode.Unspecified) { hash ^= Code.GetHashCode(); } if (arrayElementType_ != null) { hash ^= ArrayElementType.GetHashCode(); } if (structType_ != null) { hash ^= StructType.GetHashCode(); } if (TypeAnnotation != global::Google.Cloud.Spanner.V1.TypeAnnotationCode.Unspecified) { hash ^= TypeAnnotation.GetHashCode(); } if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } return(hash); }
public void MergeFrom(Type other) { if (other == null) { return; } if (other.Code != 0) { Code = other.Code; } if (other.arrayElementType_ != null) { if (arrayElementType_ == null) { arrayElementType_ = new global::Google.Cloud.Spanner.V1.Type(); } ArrayElementType.MergeFrom(other.ArrayElementType); } if (other.structType_ != null) { if (structType_ == null) { structType_ = new global::Google.Cloud.Spanner.V1.StructType(); } StructType.MergeFrom(other.StructType); } }
public void MergeFrom(Type other) { if (other == null) { return; } if (other.Code != global::Google.Cloud.Spanner.V1.TypeCode.Unspecified) { Code = other.Code; } if (other.arrayElementType_ != null) { if (arrayElementType_ == null) { ArrayElementType = new global::Google.Cloud.Spanner.V1.Type(); } ArrayElementType.MergeFrom(other.ArrayElementType); } if (other.structType_ != null) { if (structType_ == null) { StructType = new global::Google.Cloud.Spanner.V1.StructType(); } StructType.MergeFrom(other.StructType); } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
public void MergeFrom(StandardSqlDataType other) { if (other == null) { return; } if (other.TypeKind != global::Google.Cloud.Bigquery.V2.StandardSqlDataType.Types.TypeKind.Unspecified) { TypeKind = other.TypeKind; } switch (other.SubTypeCase) { case SubTypeOneofCase.ArrayElementType: if (ArrayElementType == null) { ArrayElementType = new global::Google.Cloud.Bigquery.V2.StandardSqlDataType(); } ArrayElementType.MergeFrom(other.ArrayElementType); break; case SubTypeOneofCase.StructType: if (StructType == null) { StructType = new global::Google.Cloud.Bigquery.V2.StandardSqlStructType(); } StructType.MergeFrom(other.StructType); break; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
/// <summary> /// Returns a string representation of the current object. /// </summary> /// <returns>A string representation of the current object.</returns> public override string ToString() { return(string.Format(System.Globalization.CultureInfo.InvariantCulture, "[CodeTypeInfo: Namespace={0} TypeNames={1} TypeArgumentCount={2} ArrayElementType={3} ArrayDimensions={4}]", Namespace, String.Join("+", TypeNames), String.Join("+", Array.ConvertAll <int, string>(TypeArgumentCount, IntToString)), ArrayElementType == null ? "<null>" : ArrayElementType.ToString(), ArrayDimensions)); }
private void OnArraySizeChanged(int size) { var length = ArraySize; if (length != size) { var array = Value; if (PropertyType.IsArray) { var newArray = System.Array.CreateInstance(ArrayElementType, size); if (length < size) { System.Array.Copy(array as System.Array, newArray, length); if (length > 0) { for (int i = length; i < size; i++) { System.Array.Copy(array as System.Array, length - 1, newArray, i, 1); } } } else { System.Array.Copy(array as System.Array, newArray, size); } Value = newArray; } else { if (length < size) { object lastObject = null; if (length > 0) { lastObject = getMethod.Invoke(array, new object[] { length - 1 }); } else { lastObject = ArrayElementType.GetDefaultValue(); } for (int i = length; i < size; i++) { addMethod.Invoke(array, new object[] { lastObject }); } } else { removerangeMethod.Invoke(array, new object[] { size, length - size }); } Value = array; } } ApplyModifiedArray(); }
public override int GetHashCode() { int hash = 1; if (Code != 0) { hash ^= Code.GetHashCode(); } if (arrayElementType_ != null) { hash ^= ArrayElementType.GetHashCode(); } if (structType_ != null) { hash ^= StructType.GetHashCode(); } return(hash); }
public override int GetHashCode() { int hash = 1; if (TypeKind != global::Google.Cloud.Bigquery.V2.StandardSqlDataType.Types.TypeKind.Unspecified) { hash ^= TypeKind.GetHashCode(); } if (subTypeCase_ == SubTypeOneofCase.ArrayElementType) { hash ^= ArrayElementType.GetHashCode(); } if (subTypeCase_ == SubTypeOneofCase.StructType) { hash ^= StructType.GetHashCode(); } hash ^= (int)subTypeCase_; if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } return(hash); }
public static extern IntPtr op_core_Array_toString(IntPtr array, ArrayElementType elementType);
private object ConvertToClrTypeImpl(Value wireValue, System.Type targetClrType, SpannerConversionOptions options) { //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); } if (wireValue.KindCase == Value.KindOneofCase.StructValue) { throw new InvalidOperationException($"google.protobuf.Struct values are invalid in Spanner"); } // targetClrType should be one of the values returned by DefaultClrType if (targetClrType == typeof(bool)) { switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(default(bool)); case Value.KindOneofCase.StringValue: if (TypeCode == TypeCode.Int64) { return(Convert.ToBoolean(Convert.ToInt64(wireValue.StringValue, InvariantCulture))); } return(Convert.ToBoolean(wireValue.StringValue)); case Value.KindOneofCase.BoolValue: return(wireValue.BoolValue); case Value.KindOneofCase.NumberValue: return(Convert.ToBoolean(wireValue.NumberValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(char)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToChar(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToChar(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(char)); case Value.KindOneofCase.StringValue: if (TypeCode == TypeCode.Int64) { return(Convert.ToChar(Convert.ToInt64(wireValue.StringValue, InvariantCulture))); } return(Convert.ToChar(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(long)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToInt64(wireValue.BoolValue)); 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, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(ulong)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToUInt64(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToUInt64(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(ulong)); case Value.KindOneofCase.StringValue: return(Convert.ToUInt64(wireValue.StringValue, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(decimal)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToDecimal(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToDecimal(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(decimal)); case Value.KindOneofCase.StringValue: return(Convert.ToDecimal(wireValue.StringValue, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(double)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToDouble(wireValue.BoolValue)); 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, InvariantCulture)); 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(Protobuf.WellKnownTypes.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(InvariantCulture)); 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 (targetClrType == typeof(SpannerStruct)) { if (TypeCode != TypeCode.Struct) { throw new ArgumentException( $"{targetClrType.FullName} can only be used for struct results"); } if (wireValue.KindCase != Value.KindOneofCase.ListValue) { throw new ArgumentException( $"Invalid conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } var values = wireValue.ListValue.Values; // StructFields will definitely be non-null, as we can only construct SpannerDbTypes of structs // by passing them fields. var ret = new SpannerStruct(); if (StructFields.Count != values.Count) { throw new InvalidOperationException( $"Incorrect number of struct fields. SpannerDbType has {StructFields.Count}; list has {values.Count}"); } // Could use Zip, but this is probably simpler. for (int i = 0; i < values.Count; i++) { var field = StructFields[i]; ret.Add(field.Name, field.Type, field.Type.ConvertToClrType(values[i], typeof(object), options, topLevel: false)); } return(ret); } // It's questionable as to whether we want to support this, but it does no harm to do so. if (typeof(IDictionary).IsAssignableFrom(targetClrType)) { if (targetClrType == typeof(IDictionary)) { // Default type depends on whether it's a struct or not. targetClrType = TypeCode == TypeCode.Struct ? typeof(Dictionary <string, object>) : typeof(Dictionary <int, object>); } //a bit of recursion here... IDictionary dictionary = (IDictionary)Activator.CreateInstance(targetClrType); var itemType = targetClrType.GetGenericArguments().Skip(1).FirstOrDefault() ?? typeof(object); switch (wireValue.KindCase) { case Value.KindOneofCase.ListValue: if (TypeCode == TypeCode.Struct) { for (int i = 0; i < StructFields.Count; i++) { var elementValue = wireValue.ListValue.Values[i]; var field = StructFields[i]; dictionary[field.Name] = field.Type.ConvertToClrType(elementValue, itemType, options, topLevel: false); } } else { var i = 0; foreach (var listItemValue in wireValue.ListValue.Values) { dictionary[i] = ArrayElementType.ConvertToClrType(listItemValue, itemType, options, topLevel: false); 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 => ArrayElementType.ConvertToClrType(x, targetClrType.GetElementType(), options, topLevel: false))) { newArray.SetValue(obj, i); i++; } return(newArray); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(SpannerNumeric)) { if (TypeCode != TypeCode.Numeric) { throw new ArgumentException($"{targetClrType.FullName} can only be used for numeric results"); } switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.StringValue: return(SpannerNumeric.Parse(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (typeof(IList).IsAssignableFrom(targetClrType)) { if (targetClrType == typeof(IList)) { targetClrType = typeof(List <object>); } switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.ListValue: var newList = (IList)Activator.CreateInstance(targetClrType); var itemType = targetClrType.GetGenericArguments().FirstOrDefault() ?? typeof(object); foreach (var obj in wireValue.ListValue.Values.Select( x => ArrayElementType.ConvertToClrType(x, itemType, options, topLevel: false))) { 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}"); }
// Note: the options can *currently* be null because we're not using them, but // every call site should check that it could provide options if they become required. internal Value ToProtobufValue(object value, SpannerConversionOptions options) { if (value == null || value is DBNull) { return(Value.ForNull()); } // If we add any other special values, we can create an interface to delegate to instead. if (value is CommitTimestamp ts) { return(ts.ToProtobufValue(this)); } switch (TypeCode) { case TypeCode.Bytes: if (value is string s) { return(new Value { StringValue = s }); } if (value is byte[] bArray) { return(new Value { StringValue = Convert.ToBase64String(bArray) }); } throw new ArgumentException("TypeCode.Bytes only supports string and byte[]", nameof(value)); case TypeCode.Bool: return(new Value { BoolValue = Convert.ToBoolean(value) }); case TypeCode.String: if (value is DateTime dateTime) { // If the value is a DateTime, we always convert using XmlConvert. // This allows us to convert back to a datetime reliably from the // resulting string (so roundtrip works properly if the developer uses // a string as a backing field for a datetime for whatever reason). return(new Value { StringValue = XmlConvert.ToString(dateTime, XmlDateTimeSerializationMode.Utc) }); } // All the other conversions will fail naturally, but let's make sure we don't convert structs // to strings. if (value is SpannerStruct) { throw new ArgumentException("SpannerStruct cannot be used for string parameters", nameof(value)); } return(new Value { StringValue = Convert.ToString(value, InvariantCulture) }); case TypeCode.Int64: return(new Value { StringValue = Convert.ToInt64(value, InvariantCulture) .ToString(InvariantCulture) }); case TypeCode.Float64: return(new Value { NumberValue = Convert.ToDouble(value, InvariantCulture) }); case TypeCode.Timestamp: return(new Value { StringValue = XmlConvert.ToString(Convert.ToDateTime(value, InvariantCulture), XmlDateTimeSerializationMode.Utc) }); case TypeCode.Date: return(new Value { StringValue = StripTimePart( XmlConvert.ToString(Convert.ToDateTime(value, InvariantCulture), XmlDateTimeSerializationMode.Utc)) }); case TypeCode.Array: if (value is IEnumerable enumerable) { return(Value.ForList( enumerable.Cast <object>() .Select(x => ArrayElementType.ToProtobufValue(x, options)).ToArray())); } throw new ArgumentException("The given array instance needs to implement IEnumerable."); case TypeCode.Struct: if (value is SpannerStruct spannerStruct) { return(new Value { ListValue = new ListValue { Values = { spannerStruct.Select(f => f.Type.ToProtobufValue(f.Value, options)) } } }); } throw new ArgumentException("Struct parameters must be of type SpannerStruct"); case TypeCode.Numeric: if (value is SpannerNumeric spannerNumeric) { return(Value.ForString(spannerNumeric.ToString())); } if (value is string str) { return(Value.ForString(SpannerNumeric.Parse(str).ToString())); } if (value is float || value is double || value is decimal) { // We throw if there's a loss of precision. We could use // LossOfPrecisionHandling.Truncate but GoogleSQL documentation requests to // use half-away-from-zero rounding but the SpannerNumeric implementation // truncates instead. return(Value.ForString(SpannerNumeric.FromDecimal( Convert.ToDecimal(value, InvariantCulture), LossOfPrecisionHandling.Throw).ToString())); } if (value is sbyte || value is short || value is int || value is long) { SpannerNumeric numericValue = Convert.ToInt64(value, InvariantCulture); return(Value.ForString(numericValue.ToString())); } if (value is byte || value is ushort || value is uint || value is ulong) { SpannerNumeric numericValue = Convert.ToUInt64(value, InvariantCulture); return(Value.ForString(numericValue.ToString())); } throw new ArgumentException("Numeric parameters must be of type SpannerNumeric or string"); default: throw new ArgumentOutOfRangeException(nameof(TypeCode), TypeCode, null); } }
private object ConvertToClrTypeImpl(Value wireValue, 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: if (TypeCode == TypeCode.Int64) { return(Convert.ToBoolean(Convert.ToInt64(wireValue.StringValue, InvariantCulture))); } return(Convert.ToBoolean(wireValue.StringValue)); case Value.KindOneofCase.BoolValue: return(wireValue.BoolValue); case Value.KindOneofCase.NumberValue: return(Convert.ToBoolean(wireValue.NumberValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(char)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToChar(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToChar(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(char)); case Value.KindOneofCase.StringValue: if (TypeCode == TypeCode.Int64) { return(Convert.ToChar(Convert.ToInt64(wireValue.StringValue, InvariantCulture))); } return(Convert.ToChar(wireValue.StringValue)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(long)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToInt64(wireValue.BoolValue)); 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, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(ulong)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToUInt64(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToUInt64(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(ulong)); case Value.KindOneofCase.StringValue: return(Convert.ToUInt64(wireValue.StringValue, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(decimal)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToDecimal(wireValue.BoolValue)); case Value.KindOneofCase.NumberValue: return(Convert.ToDecimal(wireValue.NumberValue)); case Value.KindOneofCase.NullValue: return(default(decimal)); case Value.KindOneofCase.StringValue: return(Convert.ToDecimal(wireValue.StringValue, InvariantCulture)); default: throw new InvalidOperationException( $"Invalid Type conversion from {wireValue.KindCase} to {targetClrType.FullName}"); } } if (targetClrType == typeof(double)) { switch (wireValue.KindCase) { case Value.KindOneofCase.BoolValue: return(Convert.ToDouble(wireValue.BoolValue)); 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, InvariantCulture)); 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(Protobuf.WellKnownTypes.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(InvariantCulture)); 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)) { #pragma warning disable DE0006 targetClrType = typeof(Hashtable); #pragma warning restore DE0006 } //a bit of recursion here... IDictionary dictionary = (IDictionary)Activator.CreateInstance(targetClrType); var itemType = targetClrType.GetGenericArguments().Skip(1).FirstOrDefault() ?? typeof(object); switch (wireValue.KindCase) { case Value.KindOneofCase.StructValue: foreach (var structField in StructMembers) { dictionary[structField.Key] = structField.Value.ConvertToClrType( wireValue.StructValue.Fields[structField.Key], itemType); } return(dictionary); case Value.KindOneofCase.ListValue: if (TypeCode == TypeCode.Struct) { for (var i = 0; i < StructOrder?.Count; i++) { dictionary[StructOrder[i]] = StructMembers[StructOrder[i]].ConvertToClrType(wireValue .ListValue.Values[i], itemType); } } else { var i = 0; foreach (var listItemValue in wireValue.ListValue.Values) { dictionary[i] = ArrayElementType.ConvertToClrType(listItemValue, itemType); 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 => ArrayElementType.ConvertToClrType(x, 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(List <object>); } switch (wireValue.KindCase) { case Value.KindOneofCase.NullValue: return(null); case Value.KindOneofCase.ListValue: var newList = (IList)Activator.CreateInstance(targetClrType); var itemType = targetClrType.GetGenericArguments().FirstOrDefault() ?? typeof(object); foreach (var obj in wireValue.ListValue.Values.Select( x => ArrayElementType.ConvertToClrType(x, itemType))) { 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}"); }
internal Value ToProtobufValue(object value) { if (value == null || value is DBNull) { return(Value.ForNull()); } switch (TypeCode) { case TypeCode.Bytes: if (value is string s) { return(new Value { StringValue = s }); } if (value is byte[] bArray) { return(new Value { StringValue = Convert.ToBase64String(bArray) }); } throw new ArgumentException("TypeCode.Bytes only supports string and byte[]", nameof(value)); case TypeCode.Bool: return(new Value { BoolValue = Convert.ToBoolean(value) }); case TypeCode.String: if (value is DateTime dateTime) { // If the value is a DateTime, we always convert using XmlConvert. // This allows us to convert back to a datetime reliably from the // resulting string (so roundtrip works properly if the developer uses // a string as a backing field for a datetime for whatever reason). return(new Value { StringValue = XmlConvert.ToString(dateTime, XmlDateTimeSerializationMode.Utc) }); } return(new Value { StringValue = Convert.ToString(value, InvariantCulture) }); case TypeCode.Int64: return(new Value { StringValue = Convert.ToInt64(value, InvariantCulture) .ToString(InvariantCulture) }); case TypeCode.Float64: return(new Value { NumberValue = Convert.ToDouble(value, InvariantCulture) }); case TypeCode.Timestamp: return(new Value { StringValue = XmlConvert.ToString(Convert.ToDateTime(value, InvariantCulture), XmlDateTimeSerializationMode.Utc) }); case TypeCode.Date: return(new Value { StringValue = StripTimePart( XmlConvert.ToString(Convert.ToDateTime(value, InvariantCulture), XmlDateTimeSerializationMode.Utc)) }); case TypeCode.Array: if (value is IEnumerable enumerable) { return(Value.ForList( enumerable.Cast <object>() .Select(x => ArrayElementType.ToProtobufValue(x)).ToArray())); } throw new ArgumentException("The given array instance needs to implement IEnumerable."); case TypeCode.Struct: if (value is IDictionary dictionary) { var structValue = new Struct(); foreach (var key in dictionary.Keys) { string keyString = Convert.ToString(key, InvariantCulture); if (!StructMembers.ContainsKey(keyString)) { throw new ArgumentException("The given struct instance has members not defined in the Struct.", nameof(value)); } structValue.Fields[keyString] = StructMembers[keyString].ToProtobufValue( dictionary[key]); } return(Value.ForStruct(structValue)); } throw new ArgumentException("The given struct instance needs to implement IDictionary."); default: throw new ArgumentOutOfRangeException(nameof(TypeCode), TypeCode, null); } }
public void Generate(CodeGenerator generator) { generator.EnterElement(this); if (ArrayElementType != null) { ArrayElementType.Generate(generator); generator.Write(TokenType.Punctuation, ArraySuffix); generator.ExitElement(); return; } var name = RawName; if (SimplifiedBuiltinTypeNames.TryGetValue(name, out var simplifiedBuiltinTypeName)) { generator.Write(TokenType.Keyword, simplifiedBuiltinTypeName); generator.ExitElement(); return; } if (name == "var") { generator.Write(TokenType.Keyword, name); generator.ExitElement(); return; } if (Global) { generator.Write(TokenType.Keyword, "global"); generator.Write(TokenType.Punctuation, "::"); } var nameBuilder = new StringBuilder(); var namespaceNameLength = 0; { var previousIndex = 0; for (var i = 0; i < name.Length; i++) { var c = name[i]; if (c == '.') { nameBuilder.Append(name.Substring(previousIndex, i - previousIndex).EscapeIdentifier()); namespaceNameLength = nameBuilder.Length; nameBuilder.Append('.'); previousIndex = i + 1; } else if (c == '+') { nameBuilder.Append(name.Substring(previousIndex, i - previousIndex).EscapeIdentifier()).Append('.'); previousIndex = i + 1; } } nameBuilder.Append(previousIndex > 0 ? name.Substring(previousIndex).EscapeIdentifier() : name.EscapeUnqualifiedTypeIdentifier()); } if (namespaceNameLength > 0) { var namespaceRef = new CodeUsingImport(nameBuilder.ToString(0, namespaceNameLength)); var usingSets = generator.UsingSets; foreach (var usingSet in usingSets) { if (usingSet.Contains(namespaceRef)) { var ambiguityDetected = false; var unqualifiedTypeName = nameBuilder.ToString(namespaceNameLength + 1, nameBuilder.Length - namespaceNameLength - 1); var unqualifiedTypeNameWithArity = unqualifiedTypeName + (TypeArguments != null && TypeArguments.Count != 0 ? "`" + TypeArguments.Count : ""); if (TypesByNames.TryGetValue(unqualifiedTypeNameWithArity, out var types)) { foreach (var type in types) { var otherNamespaceRef = new CodeUsingImport(type.NamespaceName); if (namespaceRef != otherNamespaceRef) { foreach (var otherUsingSet in usingSets) { if (otherUsingSet.Contains(otherNamespaceRef)) { ambiguityDetected = true; break; } } } if (ambiguityDetected) { break; } } } ambiguityDetected = ambiguityDetected || generator.Options.PredeclaredTypes.Where(type => type.NamespaceName != namespaceRef.Name && type.TypeName == unqualifiedTypeNameWithArity).Any(); if (!ambiguityDetected) { nameBuilder.Length = 0; nameBuilder.Append(unqualifiedTypeName); } break; } } } { var previousIndex = 0; var typeArgumentStart = 0; for (var characterIndex = 0; characterIndex < nameBuilder.Length;) { if (nameBuilder[characterIndex] == '`') { generator.OutputQualifiedName(TokenType.TypeIdentifier, nameBuilder, previousIndex, characterIndex); characterIndex++; var arity = 0; while (characterIndex < nameBuilder.Length && '0' <= nameBuilder[characterIndex] && nameBuilder[characterIndex] <= '9') { arity = arity * 10 + (nameBuilder[characterIndex] - '0'); characterIndex++; } previousIndex = characterIndex; generator.Write(TokenType.Punctuation, '<'); var first = true; for (var typeArgumentIndex = typeArgumentStart; typeArgumentIndex < typeArgumentStart + arity; typeArgumentIndex++) { var typeArgument = TypeArguments[typeArgumentIndex]; if (first) { first = false; } else { generator.Write(TokenType.Punctuation, ','); if (typeArgument != null) { generator.Write(TokenType.Space, ' '); } } if (typeArgument != null) { typeArgument.Generate(generator); } } typeArgumentStart += arity; generator.Write(TokenType.Punctuation, '>'); } else { characterIndex++; } } if (previousIndex < nameBuilder.Length) { generator.OutputQualifiedName(TokenType.TypeIdentifier, nameBuilder, previousIndex); } } generator.ExitElement(); }