Inheritance: Catel.Data.ModelBase
        private bool TryCreateDataTypeExpressionForEnum(Type propertyType, bool isNullable)
        {
            if (!propertyType.IsEnumEx())
            {
                return(false);
            }

            if (DataTypeExpression is null)
            {
                return(true);
            }

            var enumExpressionGenericType = typeof(EnumExpression <>).MakeGenericType(propertyType);

            if (enumExpressionGenericType.IsAssignableFromEx(DataTypeExpression.GetType()) &&
                (DataTypeExpression as NullableDataTypeExpression)?.IsNullable == isNullable)
            {
                return(true);
            }

            var constructorInfo = enumExpressionGenericType.GetConstructorEx(TypeArray.From <bool>());

            DataTypeExpression = (DataTypeExpression)constructorInfo?.Invoke(new object[] { isNullable });

            return(true);
        }
        private void CreateDataTypeExpressionIfNotCompatible <TDataExpression>(Func <TDataExpression> createFunc)
            where TDataExpression : DataTypeExpression
        {
            var dataTypeExpression = DataTypeExpression;

            switch (dataTypeExpression)
            {
            case TDataExpression _ when !(dataTypeExpression is NullableDataTypeExpression) || !typeof(NullableDataTypeExpression).IsAssignableFromEx(typeof(TDataExpression)):
                return;

            case TDataExpression _:
                var oldDataTypeExpression = (NullableDataTypeExpression)dataTypeExpression;
                var newDataTypeExpression = createFunc() as NullableDataTypeExpression;
                if (newDataTypeExpression is null)
                {
                    return;
                }

                if (newDataTypeExpression.IsNullable != oldDataTypeExpression.IsNullable)
                {
                    DataTypeExpression = newDataTypeExpression;
                }

                return;
            }

            DataTypeExpression = createFunc();
        }
        private void CreateDataTypeExpressionIfNotCompatible <TDataExpression>(Func <TDataExpression> createFunc)
            where TDataExpression : DataTypeExpression
        {
            if (DataTypeExpression != null)
            {
                if (DataTypeExpression is TDataExpression)
                {
                    return;
                }
            }

            DataTypeExpression = createFunc();
        }
        private void OnPropertyChanged()
        {
            if (DataTypeExpression != null)
            {
                DataTypeExpression.PropertyChanged -= OnDataTypeExpressionPropertyChanged;
            }

            if (Property.Type == typeof (int))
            {
                DataTypeExpression = new IntegerExpression(false);
            }
            else if (Property.Type == typeof (int?))
            {
                DataTypeExpression = new IntegerExpression(true);
            }
            else if (Property.Type == typeof (string))
            {
                DataTypeExpression = new StringExpression();
            }
            else if (Property.Type == typeof (DateTime))
            {
                DataTypeExpression = new DateTimeExpression(false);
            }
            else if (Property.Type == typeof (DateTime?))
            {
                DataTypeExpression = new DateTimeExpression(true);
            }
            else if (Property.Type == typeof (bool))
            {
                DataTypeExpression = new BooleanExpression();
            }
            else if (Property.Type == typeof (TimeSpan))
            {
                DataTypeExpression = new TimeSpanExpression();
            }
            else if (Property.Type == typeof (decimal))
            {
                DataTypeExpression = new DecimalExpression(false);
            }
            else if (Property.Type == typeof (decimal?))
            {
                DataTypeExpression = new DecimalExpression(true);
            }

            if (DataTypeExpression != null)
            {
                DataTypeExpression.PropertyChanged += OnDataTypeExpressionPropertyChanged;
            }
        }
		private void OnPropertyNameChanged()
		{
			if (Property.Type() == typeof (int))
				DataTypeExpression = new IntegerExpression(false);
			else if (Property.Type() == typeof (int?))
				DataTypeExpression = new IntegerExpression(true);
			else if (Property.Type() == typeof (string))
				DataTypeExpression = new StringExpression();
			else if (Property.Type() == typeof (DateTime))
				DataTypeExpression = new DateTimeExpression(false);
			else if (Property.Type() == typeof (DateTime?))
				DataTypeExpression = new DateTimeExpression(true);
			else if (Property.Type() == typeof (bool))
				DataTypeExpression = new BooleanExpression();
			else if (Property.Type() == typeof (TimeSpan))
				DataTypeExpression = new TimeSpanExpression();
			else if (Property.Type() == typeof (decimal))
				DataTypeExpression = new DecimalExpression(false);
			else if (Property.Type() == typeof (decimal?))
				DataTypeExpression = new DecimalExpression(true);
		}
        private void CreateDataTypeExpressionIfNotCompatible <TDataExpression>(Func <TDataExpression> createFunc)
            where TDataExpression : DataTypeExpression
        {
            var dataTypeExpression = DataTypeExpression;

            if (dataTypeExpression != null && dataTypeExpression is TDataExpression)
            {
                if (dataTypeExpression is NullableDataTypeExpression && typeof(NullableDataTypeExpression).IsAssignableFromEx(typeof(TDataExpression)))
                {
                    var oldDataTypeExpression = dataTypeExpression as NullableDataTypeExpression;
                    var newDataTypeExpression = createFunc() as NullableDataTypeExpression;
                    if (newDataTypeExpression.IsNullable != oldDataTypeExpression.IsNullable)
                    {
                        DataTypeExpression = newDataTypeExpression;
                    }
                }

                return;
            }

            DataTypeExpression = createFunc();
        }
        private void OnPropertyChanged()
        {
            var dataTypeExpression = DataTypeExpression;

            if (dataTypeExpression != null)
            {
                dataTypeExpression.PropertyChanged -= OnDataTypeExpressionPropertyChanged;
            }

            if (Property != null)
            {
                var  propertyType = Property.Type;
                bool isNullable   = propertyType.IsNullableType();
                if (isNullable)
                {
                    propertyType = propertyType.GetNonNullable();
                }

                if (propertyType.IsEnumEx())
                {
                    if (DataTypeExpression != null)
                    {
                        var enumExpressionGenericType = typeof(EnumExpression <>).MakeGenericType(propertyType);
                        if (!enumExpressionGenericType.IsAssignableFromEx(DataTypeExpression.GetType()) || (DataTypeExpression as NullableDataTypeExpression)?.IsNullable != isNullable)
                        {
                            var constructorInfo = enumExpressionGenericType.GetConstructor(new[] { typeof(bool) });
                            DataTypeExpression = (DataTypeExpression)constructorInfo?.Invoke(new object[] { isNullable });
                        }
                    }
                }
                else if (propertyType == typeof(byte))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new ByteExpression(isNullable));
                }
                else if (propertyType == typeof(sbyte))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new SByteExpression(isNullable));
                }
                else if (propertyType == typeof(ushort))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new UnsignedShortExpression(isNullable));
                }
                else if (propertyType == typeof(short))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new ShortExpression(isNullable));
                }
                else if (propertyType == typeof(uint))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new UnsignedIntegerExpression(isNullable));
                }
                else if (propertyType == typeof(int))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new IntegerExpression(isNullable));
                }
                else if (propertyType == typeof(ulong))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new UnsignedLongExpression(isNullable));
                }
                else if (propertyType == typeof(long))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new LongExpression(isNullable));
                }
                else if (propertyType == typeof(string))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new StringExpression());
                }
                else if (propertyType == typeof(DateTime))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new DateTimeExpression(isNullable));
                }
                else if (propertyType == typeof(bool))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new BooleanExpression());
                }
                else if (propertyType == typeof(TimeSpan))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new TimeSpanExpression(isNullable));
                }
                else if (propertyType == typeof(decimal))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new DecimalExpression(isNullable));
                }
                else if (propertyType == typeof(float))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new FloatExpression(isNullable));
                }
                else if (propertyType == typeof(double))
                {
                    CreateDataTypeExpressionIfNotCompatible(() => new DoubleExpression(isNullable));
                }
                else
                {
                    Log.Error($"Unable to create data type expression for type '{propertyType}'");
                }
            }

            dataTypeExpression = DataTypeExpression;
            if (dataTypeExpression != null)
            {
                dataTypeExpression.PropertyChanged += OnDataTypeExpressionPropertyChanged;
            }
        }