public static Value FromPropertyInfo(object poco, PropertyInfo prop, IEntityFactory entityFactory, IList <string> recursionPath) { if (prop == null) { throw new ArgumentNullException(nameof(prop), "Cannot build an entity Value without a property"); } recursionPath.Add(prop.Name); if (prop.PropertyType.GetTypeInfo().IsInterface) { throw new NotSupportedException($"\"{poco.GetType().Name}.{string.Join(".", recursionPath)}\" has \"{prop.PropertyType.Name}\" as type, but that is just an interface and is therefore not supported"); } var value = new Value { ExcludeFromIndexes = !prop.HasAttribute(typeof(IndexAttribute)) }; var propValue = prop.GetValue(poco); if (SetValue(prop.PropertyType.GetTypeOrUnderlyingNullableType(), value, propValue, entityFactory, recursionPath)) { return(value); } throw new NotSupportedException($"The type {prop.PropertyType.Name} is not supported"); }
private static bool SetValue(Type type, Value value, object propValue, IEntityFactory entityFactory, IList <string> recursionPath) { if (HandleNull(type, value, propValue, entityFactory)) { return(true); } if (HandleEnum(type, value, propValue, entityFactory)) { return(true); } if (HandleBinary(type, value, propValue, entityFactory)) { return(true); } if (HandleString(type, value, propValue, entityFactory)) { return(true); } if (HandleEnumerable(type, value, propValue, entityFactory, recursionPath)) { return(true); } if (HandleBasicTypes(type, value, propValue, entityFactory)) { return(true); } if (HandleComplexType(type, value, propValue, entityFactory, recursionPath)) { return(true); } return(false); }
private static bool HandleString(Type type, Value value, object propValue, IEntityFactory entityFactory) { if (type == typeof(string)) { value.StringValue = (string)propValue; return(true); } return(false); }
private static bool HandleComplexType(Type type, Value value, object propValue, IEntityFactory entityFactory, IList <string> recursionPath) { if (type.GetTypeInfo().IsClass) { value.EntityValue = entityFactory.EmbeddedEntityFromPoco(propValue, recursionPath); return(true); } return(false); }
private static bool HandleNull(Type type, Value value, object propValue, IEntityFactory entityFactory) { if (propValue == null) { value.NullValue = NullValue.NullValue; return(true); } return(false); }
private static bool HandleEnum(Type type, Value value, object propValue, IEntityFactory entityFactory) { if (type.GetTypeInfo().IsEnum) { value.StringValue = propValue.ToString(); return(true); } return(false); }
private static bool HandleBinary(Type type, Value value, object propValue, IEntityFactory entityFactory) { if (type.Name.Equals("Byte[]")) { var theBytes = (byte[])propValue; value.BlobValue = ByteString.CopyFrom(theBytes, 0, theBytes.Length); return(true); } return(false); }
private object CreateObjectFromValue(Value value, Type requestedType) { if (value.ValueTypeCase == Value.ValueTypeOneofCase.StringValue) { return(value.StringValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.IntegerValue) { if (requestedType == typeof(int) || requestedType == typeof(int?)) { return((int)value.IntegerValue); } if (requestedType.IsEnum) { return((int)value.IntegerValue); } return(value.IntegerValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.BooleanValue) { return(value.BooleanValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.DoubleValue) { return(value.DoubleValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.TimestampValue) { return(value.TimestampValue.ToDateTime()); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.EntityValue) { if (value.EntityValue.Properties.ContainsKey(TypesMetadataLoader.InheritedTypePropertyName)) // Handle abstract class { var inheritedTypeName = value.EntityValue.Properties[TypesMetadataLoader.InheritedTypePropertyName].StringValue; var inheritedType = _typesMetadataLoader.GetTypeMetadata(inheritedTypeName); return(FromEntity(value.EntityValue, inheritedType)); } return(FromEntity(value.EntityValue, requestedType)); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.ArrayValue) { var typeMetadata = _typesMetadataLoader.GetTypeMetadata(requestedType) as ListMetadata; var obj = typeMetadata.Constructor(); foreach (var item in value.ArrayValue.Values) { typeMetadata.AddItem(obj, CreateObjectFromValue(item, typeMetadata.ItemsType)); } return(obj); } return(null); }
private static bool HandleEnumerable(Type type, Value value, object propValue, IEntityFactory entityFactory, IList <string> recursionPath) { if (type.ImplementsInterface(typeof(IEnumerable))) { value.ExcludeFromIndexes = false; // Exclude from indexes cannot be set on a list value value.ArrayValue = new ArrayValue(); foreach (object item in (IEnumerable)propValue) { var itemValue = new Value(); SetValue(item.GetType(), itemValue, item, entityFactory, recursionPath); value.ArrayValue.Values.Add(itemValue); } return(true); } return(false); }
private object CreateObjectFromValue(Value value, System.Type requestedType, System.Type thisEntityType = null) { if (value.ValueTypeCase == Value.ValueTypeOneofCase.StringValue) { return(value.StringValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.IntegerValue) { if (requestedType == typeof(int) || requestedType == typeof(int?)) { return((int)value.IntegerValue); } if (requestedType.GetTypeInfo().IsEnum) { return((int)value.IntegerValue); } return(value.IntegerValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.BooleanValue) { return(value.BooleanValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.DoubleValue) { return(value.DoubleValue); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.TimestampValue) { if (requestedType == typeof(DateTimeOffset)) { return(value.TimestampValue.ToDateTimeOffset()); } return(value.TimestampValue.ToDateTime()); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.EntityValue) { if (thisEntityType != null) { return(FromEntity(value.EntityValue, thisEntityType)); } return(FromEntity(value.EntityValue, requestedType)); } if (value.ValueTypeCase == Value.ValueTypeOneofCase.ArrayValue) { var requestedTypeInfo = requestedType.GetTypeInfo(); var isDictionary = requestedTypeInfo.IsGenericType && requestedTypeInfo.GetGenericTypeDefinition() == typeof(IDictionary <,>); if (isDictionary) { var t1 = requestedType.GetGenericArguments()[0]; var t2 = requestedType.GetGenericArguments()[1]; var dictType = typeof(Dictionary <,>).MakeGenericType(t1, t2); var dictionary = (IDictionary)Activator.CreateInstance(dictType); // TODO: Implement mapping of Dicitionary collection here. foreach (var item in value.ArrayValue.Values) { } return(dictionary); } var list = (IList)Activator.CreateInstance(requestedType); var listArgType = requestedType.GetGenericArguments()[0]; foreach (var item in value.ArrayValue.Values) { list.Add(CreateObjectFromValue(item, listArgType)); } return(list); } return(null); }
private Value CreateValueFromObject(object obj, bool isExcludeFromIndex = false) { var value = new Value { ExcludeFromIndexes = isExcludeFromIndex }; if (obj == null) { value.NullValue = NullValue.NullValue; return(value); } var type = obj.GetType(); if (type == typeof(string)) { value.StringValue = (string)obj; } else if (type == typeof(int)) { value.IntegerValue = (int)obj; } else if (type == typeof(long)) { value.IntegerValue = (long)obj; } else if (type == typeof(double)) { value.DoubleValue = (double)obj; } else if (type == typeof(float)) { value.DoubleValue = (float)obj; } else if (type == typeof(bool)) { value.BooleanValue = (bool)obj; } else if (type == typeof(DateTime)) { value.TimestampValue = ((DateTime)obj).ToTimestamp(); } else if (type == typeof(DateTimeOffset)) { value.TimestampValue = ((DateTimeOffset)obj).ToTimestamp(); } else if (type.GetTypeInfo().IsEnum) { value.IntegerValue = (int)obj; } else if (typeof(ICollection).IsAssignableFrom(type)) { var list = obj as ICollection; value.ArrayValue = new ArrayValue(); if (list != null) //TODO: Otherwise should add warn logs { foreach (var item in list) { value.ArrayValue.Values.Add(CreateValueFromObject(item)); } } } else if (type.GetTypeInfo().IsClass) { value.EntityValue = new Entity(); foreach (var property in type.GetRuntimeProperties()) { var propName = property.Name; var propValue = property.GetValue(obj); value.EntityValue.Properties.Add(propName, CreateValueFromObject(propValue)); // TODO: Should call ToEntity - but should have depth consideration in regarding to the key } } return(value); }
private Value CreateValueFromObject(object obj, bool isExcludeFromIndex = false) { var value = new Value { ExcludeFromIndexes = isExcludeFromIndex }; if (obj == null) { value.NullValue = NullValue.NullValue; return(value); } var type = obj.GetType(); if (type == typeof(string)) { value.StringValue = (string)obj; } else if (type == typeof(int)) { value.IntegerValue = (int)obj; } else if (type == typeof(long)) { value.IntegerValue = (long)obj; } else if (type == typeof(double)) { value.DoubleValue = (double)obj; } else if (type == typeof(float)) { value.DoubleValue = (float)obj; } else if (type == typeof(bool)) { value.BooleanValue = (bool)obj; } else if (type == typeof(DateTime)) { value.TimestampValue = ((DateTime)obj).ToTimestamp(); } else if (type.IsEnum) { value.IntegerValue = (int)obj; } else if (typeof(ICollection).IsAssignableFrom(type)) { var list = obj as ICollection; value.ArrayValue = new ArrayValue(); var listType = _typesMetadataLoader.GetTypeMetadata(type); if (listType != null && list != null) //TODO: Otherwise should add warn logs { foreach (var item in list) { value.ArrayValue.Values.Add(CreateValueFromObject(item)); } } } else if (type.IsClass) { value.EntityValue = new Entity(); var classMetadata = _typesMetadataLoader.GetTypeMetadata(type); if (classMetadata != null) { if (!string.IsNullOrEmpty(classMetadata.InheritedClassType)) { value.EntityValue.Properties.Add(TypesMetadataLoader.InheritedTypePropertyName, classMetadata.InheritedClassType); } foreach (var property in classMetadata.PropertiesInfo) { var val = property.Value.Get(obj); value.EntityValue.Properties.Add(property.Key, CreateValueFromObject(val, IsExcludeColumnFromIndex(property.Value.CustomAttributes))); // TODO: Should call ToEntity - but should have depth consideration in regarding to the key } } } return(value); }
protected override void ProcessRecord() { base.ProcessRecord(); var db = DatastoreDb.Create(Project); var keyFactory = db.CreateKeyFactory(Kind); _gKey = string.IsNullOrEmpty(Key) ? keyFactory.CreateIncompleteKey() : keyFactory.CreateKey(Key); var entity = new Entity(); entity.Key = _gKey; foreach (var k in Properties.Keys) { var val = new Value(); switch (Properties[k]) {// I'm surprised there's no built in method in Value to handle this scenario case NullValue c: { val.NullValue = c; break; } case bool c: { val.BooleanValue = c; break; } case int c: { val.IntegerValue = (long)c; break; } case long c: { val.IntegerValue = c; break; } case float c: { val.DoubleValue = (double)c; break; } case double c: { val.DoubleValue = c; break; } case Timestamp c: { val.TimestampValue = c; break; } case DateTime c: { val.TimestampValue = c.ToTimestamp(); break; } case Cloud.Datastore.V1.Key c: { val.KeyValue = c; break; } case string c: { val.StringValue = c; break; } case byte[] c: { if (c.Length > 1000000) { var e = new ArgumentException("Max byte count exceeded"); var er = new ErrorRecord(e, "ByteCountLimitExceeded", ErrorCategory.InvalidData, Properties); ThrowTerminatingError(er); } val.BlobValue = ByteString.CopyFrom(c); break; } case LatLng c: { val.GeoPointValue = c; break; } case Entity c: { val.EntityValue = c; break; } case ArrayValue c: { val.ArrayValue = c; break; } default: { // It's either this or throw - not sure of best approach WriteWarning($"Unexpected type in properties dictionary: {Properties[k].GetType().FullName}"); val.StringValue = Properties[k].ToString(); break; } } entity.Properties.Add(k.ToString(), val); } WriteObject(entity); }
private static bool HandleBasicTypes(Type type, Value value, object propValue, IEntityFactory entityFactory) { switch (type.Name) { case "Char": value.StringValue = propValue.ToString(); break; case "Boolean": value.BooleanValue = (bool)propValue; break; case "Byte": value.IntegerValue = (byte)propValue; break; case "Int16": value.IntegerValue = (short)propValue; break; case "Int32": value.IntegerValue = (int)propValue; break; case "Int64": value.IntegerValue = (long)propValue; break; case "Single": value.DoubleValue = double.Parse(propValue.ToString()); break; case "Double": value.DoubleValue = (double)propValue; break; case "Decimal": var dec = (decimal)propValue; var integral = Convert.ToInt64(decimal.Truncate(dec)); var fraction = Convert.ToDouble(dec % 1m); value.EntityValue = new Entity { ["integral"] = new Value { IntegerValue = integral, ExcludeFromIndexes = true }, ["fraction"] = new Value { DoubleValue = fraction, ExcludeFromIndexes = true } }; break; case "DateTime": value.TimestampValue = Timestamp.FromDateTime((DateTime)propValue); break; case "DateTimeOffset": value.TimestampValue = Timestamp.FromDateTimeOffset((DateTimeOffset)propValue); break; case "TimeSpan": value.IntegerValue = ((TimeSpan)propValue).Ticks; break; default: return(false); } return(true); }