public override Expression <Func <TModel, bool> > GetExpression <TModel>(IColumn column, ISearch search, ParameterExpression parameterExpression)
        {
            var sourcePropertyName = column.Field ?? column.Name;
            var sourceProperty     = GetProperty <TModel> .ByName(sourcePropertyName);

            var sourcePropertyType = sourceProperty.PropertyType;
            var sourceNullableType = Nullable.GetUnderlyingType(sourcePropertyType);

            Expression property = Expression.Property(parameterExpression, sourceProperty);
            bool       canBeConvertedToColumnType = TryConvert(search.Value, out TColumn filterValue);

            if (canBeConvertedToColumnType)
            {
                if (TargetType.Equals(sourcePropertyType))
                {
                    Expression valueCheck = Expression.Equal(property, Expression.Constant(filterValue));

                    return(Expression.Lambda <Func <TModel, bool> >(valueCheck, new ParameterExpression[] { parameterExpression }));
                }
                else if (TargetType.Equals(sourceNullableType))
                {
                    Expression nullCheck  = Expression.NotEqual(property, Expression.Constant(null, sourcePropertyType));
                    Expression valueCheck = Expression.Equal(property, Expression.Convert(Expression.Constant(filterValue), sourcePropertyType));

                    //Expression.Lambda
                    return(Expression.Lambda <Func <TModel, bool> >(Expression.AndAlso(nullCheck, valueCheck), new ParameterExpression[] { parameterExpression }));
                }
            }
            return(null);
        }
        private IEnumerable <Expression <Func <TModel, object> > > GetSortExpression(IColumn column, ISort sortValue)
        {
            var sourcePropertyName = column.Field ?? column.Name;
            var sourceProperty     = GetProperty <TModel> .ByName(sourcePropertyName);

            var sourcePropertyType = sourceProperty.PropertyType;
            var sourceNullableType = Nullable.GetUnderlyingType(sourcePropertyType);

            if (sourceProperty == null)
            {
                throw new DataTablesException(string.Format(CultureInfo.CurrentUICulture, "Cannot find a Get-property with the name '{0}' on type '{1}'", sourcePropertyName, typeof(TModel).FullName));
            }

            var expression = Expression.Property(parameterExpression, sourceProperty);

            if (sourceNullableType != null)
            {
                var hasValueExpression = Expression.Convert(Expression.Property(expression, "HasValue"), typeof(object));
                var valueExpression    = Expression.Convert(Expression.Property(expression, "Value"), typeof(object));

                yield return(Expression.Lambda <Func <TModel, object> >(hasValueExpression, new ParameterExpression[] { parameterExpression }));

                yield return(Expression.Lambda <Func <TModel, object> >(valueExpression, new ParameterExpression[] { parameterExpression }));
            }
            else
            {
                yield return(Expression.Lambda <Func <TModel, object> >(expression, new ParameterExpression[] { parameterExpression }));
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="column"></param>
        /// <param name="search"></param>
        /// <param name="parameterExpression"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">Thrown when the searchquery is based on an regular expression</exception>
        public override Expression <Func <TModel, bool> > GetExpression <TModel>(IColumn column, ISearch search, ParameterExpression parameterExpression)
        {
            var sourcePropertyName = column.Field ?? column.Name;
            var sourceProperty     = GetProperty <TModel> .ByName(sourcePropertyName);

            var logicalMethod = TargetType.GetMethod(nameof(string.Contains), new[] { typeof(string), typeof(StringComparison) });
            var expression    = Expression.Call(Expression.Property(parameterExpression, sourceProperty), logicalMethod, Expression.Constant(search.Value), Expression.Constant(StringComparison.CurrentCultureIgnoreCase));

            return(Expression.Lambda <Func <TModel, bool> >(expression, new ParameterExpression[] { parameterExpression }));
        }
        public virtual void ValidateCreateExpressionCall <TModel>(IColumn column, ISearch search, ParameterExpression parameterExpression)
        {
            if (search.IsRegex && SupportsReqularExpressions == false)
            {
                throw new NotSupportedException($"The expression creator {this.GetType().FullName} does not support regular expressions.");
            }

            var sourcePropertyName = column.Field ?? column.Name;
            var sourceProperty     = GetProperty <TModel> .ByName(sourcePropertyName);

            if (sourceProperty == null)
            {
                throw new ArgumentOutOfRangeException(nameof(column), $"The column '{sourcePropertyName}' is not a property of the model '{typeof(TModel).FullName}'");
            }
        }
        private Expression <Func <TModel, bool> > GetFilterExpression(IColumn column, ISearch search, IEnumerable <IPropertyExpressionCreator> propertyExpressionCreators)
        {
            var sourcePropertyName = column.Field ?? column.Name;
            var sourceProperty     = GetProperty <TModel> .ByName(sourcePropertyName);

            if (sourceProperty == null)
            {
                throw new DataTablesException(string.Format(CultureInfo.CurrentUICulture, "Cannot find a Get-property with the name '{0}' on type '{1}'", sourcePropertyName, typeof(TModel).FullName));
            }

            var sourcePropertyType = sourceProperty.PropertyType;
            var sourceNullableType = Nullable.GetUnderlyingType(sourcePropertyType);

            var expressionCreator = propertyExpressionCreators.FirstOrDefault(creator => creator.TargetType.Equals(sourcePropertyType) ||
                                                                              creator.TargetType.Equals(sourceNullableType));

            if (expressionCreator == null)
            {
                throw new DataTablesException(string.Format(CultureInfo.CurrentUICulture, "Cannot find an Expression Creator for type '{0}'", sourceProperty.PropertyType.FullName));
            }

            return(expressionCreator.CreateExpression <TModel>(column, search, parameterExpression));
        }