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