/// <summary> /// Converts a property to the given type /// </summary> /// <param name="name">Name of the property to convert</param> /// <param name="type">Type to convert to</param> /// <param name="defaultValue">Default value to use if conversion fails</param> public MigrationContainer ConvertValueOrDefault(string name, Type type, object defaultValue = null) { var property = m_PropertyBag.FindProperty(name); if (null == property) { throw new Exception($"{nameof(MigrationContainer)}.{nameof(ConvertValueOrDefault)} no property found with the name `{name}`"); } // @TODO Type check // Grab the existing value var value = (property as IValueProperty)?.GetObjectValue(this); // Setup the backing storage for the value if (null != value) { // Try to convert the object to the new type. If this fails, fallback to the defaultValue m_Data[name] = TypeConversion.Convert(value, type) ?? defaultValue; } else { // @NOTE We do NOT assign the default value in this path since the value might have been explicitly set to null m_Data[name] = null; } // Replace the property with a newly generated one of the correct type m_PropertyBag.ReplaceProperty(name, DynamicProperties.CreateValueProperty(name, type)); return(this); }
/// <summary> /// Creates a new dynamic migration container /// </summary> /// <param name="name">Name of the new property to create</param> public MigrationContainer CreateContainer(string name) { if (null != m_PropertyBag.FindProperty(name)) { throw new Exception($"{nameof(MigrationContainer)}.{nameof(CreateContainer)} property already exists with the `{name}`"); } var container = new MigrationContainer(); m_Data[name] = container; m_PropertyBag.AddProperty(DynamicProperties.CreateValueProperty(name, typeof(MigrationContainer))); return(container); }
/// <summary> /// Creates a new value property of the given type with the default value /// </summary> /// <param name="name">Name of the property to create</param> public MigrationContainer CreateValue <TValue>(string name) { var property = m_PropertyBag.FindProperty(name); if (null != property) { throw new Exception($"{nameof(MigrationContainer)}.{nameof(CreateValue)} property already exists with the name `{name}`"); } m_Data[name] = default(TValue); m_PropertyBag.AddProperty(DynamicProperties.CreateValueProperty(name, typeof(TValue))); return(this); }
/// <summary> /// Gets a container property wrapped as a `MigrationContainer` /// </summary> /// <param name="name">Name of the property to get</param> public MigrationContainer GetContainer(string name) { var property = m_PropertyBag.FindProperty(name); if (null == property) { throw new Exception($"{nameof(MigrationContainer)}.{nameof(GetContainer)} no property found with the name `{name}`"); } // @TODO Type check MigrationContainer container; if (m_Data.ContainsKey(name)) { // The value has already been moved to dynamic storage var value = m_Data[name]; Assert.IsTrue(value is IPropertyContainer); if (value is MigrationContainer) { // Already been promoted to a `MigrationContainer` return the value return((MigrationContainer)m_Data[name]); } // This value exists in dynamic storage but NOT as a `MigrationContainer` // This can happen if the property was renamed container = new MigrationContainer(value as IPropertyContainer); m_Data[name] = container; m_PropertyBag.ReplaceProperty(name, DynamicProperties.CreateValueProperty(name, typeof(MigrationContainer))); } else { // The value has not been moved to dynamic storage var backing = (property as IValueProperty)?.GetObjectValue(this) as IPropertyContainer; Assert.IsNotNull(backing); // Wrap the value in a `MigrationContainer` and store in dynamic storage container = new MigrationContainer(backing); m_Data[name] = container; m_PropertyBag.ReplaceProperty(name, DynamicProperties.CreateValueProperty(name, typeof(MigrationContainer))); } return(container); }
/// <summary> /// Renames a property /// </summary> /// <param name="name">Name of the property to rename</param> /// <param name="newName">New name for the property</param> public MigrationContainer Rename(string name, string newName) { var property = m_PropertyBag.FindProperty(name); if (null == property) { throw new MigrationException($"{nameof(MigrationContainer)}.{nameof(Rename)} no property found with the name `{name}`"); } if (null != m_PropertyBag.FindProperty(newName)) { throw new MigrationException($"{nameof(MigrationContainer)}.{nameof(Rename)} property already exists with name `{newName}`"); } var valueProperty = property as IValueProperty; if (null != valueProperty) { var value = (property as IValueProperty).GetObjectValue(this); var valueType = valueProperty.ValueType; // If needed we promote this object to a migration container // This is because we don't support strongly typed dynamic containers (only MigrationContainers) if (typeof(IPropertyContainer).IsAssignableFrom(valueProperty.ValueType)) { value = new MigrationContainer(value as IPropertyContainer); valueType = typeof(MigrationContainer); } // Setup the backing storage for the value m_Data[newName] = value; m_PropertyBag.ReplaceProperty(name, DynamicProperties.CreateValueProperty(newName, valueType)); // Clear old dynamic value if any if (m_Data.ContainsKey(name)) { m_Data.Remove(name); } } return(this); }