using System; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { /// /// A Property contains a single piece of data /// [Serializable] [DataContract(IsReference = true)] public class Property : Entity { private readonly PropertyType _propertyType; private Guid _version; private object _value; protected Property() { } public Property(PropertyType propertyType) { _propertyType = propertyType; } public Property(PropertyType propertyType, object value) { _propertyType = propertyType; Value = value; } public Property(int id, Guid version, PropertyType propertyType, object value) { Id = id; _propertyType = propertyType; _version = version; Value = value; } private static readonly PropertyInfo ValueSelector = ExpressionHelper.GetPropertyInfo(x => x.Value); private static readonly PropertyInfo VersionSelector = ExpressionHelper.GetPropertyInfo(x => x.Version); /// /// Returns the Alias of the PropertyType, which this Property is based on /// [DataMember] public string Alias { get { return _propertyType.Alias; } } /// /// Returns the Id of the PropertyType, which this Property is based on /// [IgnoreDataMember] internal int PropertyTypeId { get { return _propertyType.Id; } } /// /// Returns the DatabaseType that the underlaying DataType is using to store its values /// /// Only used internally when saving the property value [IgnoreDataMember] internal DataTypeDatabaseType DataTypeDatabaseType { get { return _propertyType.DataTypeDatabaseType; } } /// /// Returns the PropertyType, which this Property is based on /// [IgnoreDataMember] internal PropertyType PropertyType { get { return _propertyType; } } /// /// Gets or Sets the version id for the Property /// /// /// The version will be the same for all Property objects in a collection on a Content /// object, so not sure how much this makes sense but adding it to align with: /// umbraco.interfaces.IProperty /// [DataMember] public Guid Version { get { return _version; } set { _version = value; OnPropertyChanged(VersionSelector); } } /// /// Gets or Sets the value of the Property /// /// /// Setting the value will trigger a type validation. /// The type of the value has to be valid in order to be saved. /// [DataMember] public object Value { get { return _value; } set { bool typeValidation = _propertyType.IsPropertyTypeValid(value); if (!typeValidation) throw new Exception( string.Format( "Type validation failed. The value type: '{0}' does not match the DataType in PropertyType with alias: '{1}'", value == null ? "null" : value.GetType().Name, Alias)); _value = value; OnPropertyChanged(ValueSelector); } } /// /// Boolean indicating whether the current value is valid /// /// /// A valid value implies that it is ready for publishing. /// Invalid property values can be saved, but not published. /// /// True is property value is valid, otherwise false public bool IsValid() { return IsValid(Value); } /// /// Boolean indicating whether the passed in value is valid /// /// /// True is property value is valid, otherwise false public bool IsValid(object value) { return _propertyType.IsPropertyValueValid(value); } } }