How to Type Cast dynamically to string while using Contains in Dynamic LINQ?

纵然是瞬间 提交于 2019-11-30 22:33:05

Well, you probably know that's it's not possible to use ToString() in linq to entities.

So the following question is : how can I convert other types to string.

For numeric values, you have SqlFunctions.StringConvert, but it has only overloads for double? and decimal?

For DateTime, you may find something using SqlFunctions.StringConvert after having applied SqlFunctions.DatePart on your DateTime (which probably means at least 3 call to SqlFunctions.DatePart, for year, month, day)

For Guid, I don't think there's a way to do it directly. One way (at db level, if you use Sql Server) could be to have a Computed column. The computed column could store a varchar converted representation of your GUID. Maybe there's a better way.

Anyway, here's at least a sample which should work for integer as well as string:

 public static Expression<Func<T, bool>> ContainsExp<T>(string propertyName, string contains)
        {

            //first, get the type of your property
            var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
            //no change
            var parameterExp = Expression.Parameter(typeof (T), "type");
            Expression propertyExp = Expression.Property(parameterExp, propertyName);
            //if property's type is int
            if (propertyType == typeof (int))
            {
                //convert your Expression to a nullable double (or nullable decimal),
                //so that you can use SqlFunctions.StringConvert
                propertyExp = Expression.Convert(propertyExp, typeof (double?));
                //get the SqlFunctions.StringConvert method for nullable double
                var stringConvertMethod = typeof (SqlFunctions).GetMethod("StringConvert", new[] {typeof (double?)});
                //call StringConvert on your converted expression
                propertyExp = Expression.Call(stringConvertMethod , propertyExp);
            }
            //no change
            var method = typeof (string).GetMethod("Contains", new[] {typeof (string)});


            var someValue = Expression.Constant(contains, typeof (string));
            var containsMethodExp = Expression.Call(propertyExp, method, someValue);

            return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);

        }
 public static IQueryable<T> FieldsContains<T>(this IQueryable<T> query, List<string> fileds, string searchValue)
    {
        Expression predicate = null;
        var parameterExpression = Expression.Parameter(typeof(T), "type");

        foreach (string field in fileds)
        {
            var next = GetFieldContainsExpression<T>(parameterExpression, field, searchValue);

            if (predicate == null)
            {
                predicate = next;
            }
            else
            {
                predicate = Expression.Or(predicate, next);
            }
        }

        var lambda = Expression.Lambda<Func<T, bool>>(predicate, parameterExpression);

        return query.Where(lambda);
    }

    private static Expression GetFieldContainsExpression<T>(ParameterExpression parameterExpression, string field, string value)
    {
        var propertyType = typeof(T).GetProperty(field).PropertyType;
        Expression propertyExpression = Expression.Property(parameterExpression, field);

        var filterValue = Expression.Constant(value);
        var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });

        //call toString first to ignore type errors(datetime, int ...)
        var toStringExpression = Expression.Call(propertyExpression, "ToString", Type.EmptyTypes);
        var containsExpression = Expression.Call(toStringExpression, method, filterValue);

        return containsExpression;
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!