尝试开发新的扩展方法 [英] Trying to develop a new extension method
问题描述
我正在使用Entity Framework,并且开发了此扩展方法:
I'm using the Entity Framework and I developed this extension method:
public static IQueryable<TResult> Like<TResult>(this IQueryable<TResult> query, Expression<Func<TResult, string>> field, string value)
{
var expression = Expression.Lambda<Func<TResult, bool>>(
Expression.Call(field.Body, typeof(string).GetMethod("Contains"),
Expression.Constant(value)), field.Parameters);
return query.Where(expression);
}
如果我这样使用,则此代码可以正常工作:
this code work correctly if I use it like this:
var result = from e in context.es.Like(r => r.Field, "xxx")
select e
现在,我需要以编程方式调用此扩展方法:
Now I need to call this extension method programmatically:
public static IQueryable<TSource> SearchInText<TSource>(this IQueryable<TSource> source, string textToFind)
{
// Collect fields
PropertyInfo[] propertiesInfo = source.ElementType.GetProperties();
List<string> fields = new List<string>();
foreach (PropertyInfo propertyInfo in propertiesInfo)
{
if (
(propertyInfo.PropertyType == typeof(string)) ||
(propertyInfo.PropertyType == typeof(int)) ||
(propertyInfo.PropertyType == typeof(long)) ||
(propertyInfo.PropertyType == typeof(byte)) ||
(propertyInfo.PropertyType == typeof(short))
)
{
fields.Add(propertyInfo.Name);
}
}
ParameterExpression parameter = Expression.Parameter(typeof(TSource), source.ElementType.Name);
Expression expression = Expression.Lambda(Expression.Property(parameter, typeof(TSource).GetProperty(fields[0])), parameter);
Expression<Func<TSource, string>> field = Expression.Lambda<Func<TSource, string>>(expression, parameter);
return source.Like(field, textToFind);
}
现在此代码不起作用! 我需要了解如何声明Like扩展方法的字段".
Now this code doesn't work! I need to understand how to declare the "field" of the Like extended methods.
Expression<Func<TSource, string>> field = Expression.Lambda<Func<TSource, string>>(expression, parameter);
在运行时,我收到以下错误消息:每次未恢复到"System.String"状态时,就无法使用utilizzare对系统'System.Func`2 [TestMdf.Equipment,System.String]进行压缩
At runtime I receive this error: Impossibile utilizzare un'espressione di tipo 'System.Func`2[TestMdf.Equipment,System.String]' per un tipo restituito 'System.String'
推荐答案
这是我的第一个版本:
public static IQueryable<TSource> SearchInText<TSource>(this IQueryable<TSource> source, string textToFind)
{
if (textToFind.Trim() == "")
{
return source;
}
string[] textToFindList = textToFind.Replace("'", "''").Split(' ');
// Collect fields
PropertyInfo[] propertiesInfo = source.ElementType.GetProperties();
List<string> fieldList = new List<string>();
foreach (PropertyInfo propertyInfo in propertiesInfo)
{
if (
(propertyInfo.PropertyType == typeof(string)) ||
(propertyInfo.PropertyType == typeof(int)) ||
(propertyInfo.PropertyType == typeof(long)) ||
(propertyInfo.PropertyType == typeof(byte)) ||
(propertyInfo.PropertyType == typeof(short))
)
{
fieldList.Add(propertyInfo.Name);
}
}
ParameterExpression parameter = Expression.Parameter(typeof(TSource), source.ElementType.Name);
MethodInfo concatMethod = typeof(String).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
var spaceExpression = Expression.Constant(" ");
var concatenatedField = BinaryExpression.Add(spaceExpression, Expression.MakeMemberAccess(parameter, typeof(TSource).GetProperty(fieldList[0])), concatMethod);
for (int i = 1; i < fieldList.Count; i++)
{
concatenatedField = BinaryExpression.Add(concatenatedField, spaceExpression, concatMethod);
concatenatedField = BinaryExpression.Add(concatenatedField, Expression.MakeMemberAccess(parameter, typeof(TSource).GetProperty(fieldList[i])), concatMethod);
}
concatenatedField = BinaryExpression.Add(concatenatedField, spaceExpression, concatMethod);
var fieldsExpression = Expression.Call(concatenatedField, "ToUpper", null, null);
var clauseExpression = Expression.Call(
fieldsExpression, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(textToFindList[0].ToUpper())
);
if (textToFindList.Length == 1)
{
return source.Where(Expression.Lambda<Func<TSource, bool>>(clauseExpression, parameter));
}
BinaryExpression expression = Expression.And(Expression.Call(
fieldsExpression, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(textToFindList[1].ToUpper())
), clauseExpression);
for (int i = 2; i < textToFindList.Length; i++)
{
expression = Expression.And(Expression.Call(
fieldsExpression, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(textToFindList[i].ToUpper())
), expression);
}
return source.Where(Expression.Lambda<Func<TSource, bool>>(expression, parameter));
}
我将进行修改以管理一些规则,例如短语" +和-运算符.
I will modify to manage some rules like "phrase" + and - operator.
这篇关于尝试开发新的扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!