C# 在动态LINQ中使用Contains时,如何将Cast动态类型转换为字符串?

C# 在动态LINQ中使用Contains时,如何将Cast动态类型转换为字符串?,c#,linq,entity-framework,linq-to-entities,dynamic-linq,C#,Linq,Entity Framework,Linq To Entities,Dynamic Linq,我想使用动态LINQ查询来搜索类中所有属性中的一些文本。我使用下面的函数来创建表达式。我正在将属性名和搜索文本传递给该方法。 在该方法中,如果属性类型是String,那么它工作正常。如果属性类型为int、DateTime、GUID。那么它就不起作用了 正如我们所知,Contains方法仅用于元素数组或字符串。我认为属性的值应该类型cast to string。那么怎么做呢?带解释的解决方案是完全有帮助的 我从中收集代码 公共静态表达式containsXP(string propertyName,

我想使用动态LINQ查询来搜索类中所有属性中的一些文本。我使用下面的函数来创建表达式。我正在将属性名和搜索文本传递给该方法。 在该方法中,如果属性类型是String,那么它工作正常。如果属性类型为int、DateTime、GUID。那么它就不起作用了

正如我们所知,Contains方法仅用于元素数组或字符串。我认为属性的值应该类型cast to string。那么怎么做呢?带解释的解决方案是完全有帮助的

我从中收集代码

公共静态表达式containsXP(string propertyName,string contains)
{
var parameterExp=表达式参数(typeof(T),“type”);
var propertyExp=Expression.Property(parameterExp,propertyName);
MethodInfo method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
var someValue=Expression.Constant(contains,typeof(string));
var containsMethodExp=Expression.Call(propertyExp,method,someValue);
返回表达式.Lambda(containsMethodex,parameterExp);
}

您可能知道,在linq to实体中不可能使用
ToString()

因此,下面的问题是:如何将其他类型转换为字符串

对于数值,您有
SqlFunctions.StringConvert
,但它只有
double?
decimal?
的重载

对于DateTime,在
DateTime
上应用
SqlFunctions.DatePart
后,您可以使用
SqlFunctions.StringConvert
找到一些内容(这可能意味着至少3次调用
SqlFunctions.DatePart
,例如年、月、日)

对于Guid,我不认为有直接的方法。一种方法(如果使用Sql Server,则在db级别)是使用计算列。计算列可以存储GUID的varchar转换表示形式。也许有更好的办法

无论如何,这里至少有一个示例可以用于
integer
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);

        }
公共静态表达式containsXP(string propertyName,string contains)
{
//首先,获取您的属性类型
var propertyType=typeof(T).GetProperty(propertyName).propertyType;
//不变
var parameterExp=表达式参数(typeof(T),“type”);
Expression propertyExp=Expression.Property(参数exp,propertyName);
//如果属性的类型为int
if(propertyType==typeof(int))
{
//将表达式转换为可为空的双精度(或可为空的十进制),
//这样您就可以使用SqlFunctions.StringConvert了
propertyExp=Expression.Convert(propertyExp,typeof(double?);
//获取可为null的double的SqlFunctions.StringConvert方法
var stringConvertMethod=typeof(SqlFunctions).GetMethod(“StringConvert”,新[]{typeof(double?});
//对已转换的表达式调用StringConvert
propertyExp=Expression.Call(stringConvertMethod,propertyExp);
}
//不变
var method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
var someValue=Expression.Constant(contains,typeof(string));
var containsMethodExp=Expression.Call(propertyExp,method,someValue);
返回表达式.Lambda(containsMethodex,parameterExp);
}
公共静态IQueryable字段包含(此IQueryable查询、列表文件、字符串搜索值)
{
表达式谓词=null;
var parameterExpression=Expression.Parameter(typeof(T),“type”);
foreach(文件中的字符串字段)
{
var next=GetFieldContainesPression(参数表达式、字段、搜索值);
if(谓词==null)
{
谓词=下一个;
}
其他的
{
谓词=表达式。或(谓词,下一个);
}
}
var lambda=Expression.lambda(谓词,参数Expression);
返回查询.Where(lambda);
}
私有静态表达式GetFieldContainesPression(ParameterExpression ParameterExpression,字符串字段,字符串值)
{
var-propertyType=typeof(T).GetProperty(field).propertyType;
Expression propertyExpression=Expression.Property(parameterExpression,字段);
var filterValue=表达式常数(值);
var method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
//首先调用toString忽略类型错误(datetime,int…)
var-toStringExpression=Expression.Call(propertyExpression,“ToString”,Type.EmptyTypes);
var containsPression=Expression.Call(toString表达式、方法、filterValue);
返回容器压力;
}

不确定是否理解:您想在
日期时间
上使用
字符串。包含
?更新问题以更好地理解。我想要包含的动态Linq查询。当前代码在使用字符串数据类型时运行良好。它不适用于其他数据类型(int、DateTime、GUID)。
 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;
    }