Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尝试开发一种新的扩展方法_C#_Linq_Entity Framework_Linq To Entities_Lambda - Fatal编程技术网

C# 尝试开发一种新的扩展方法

C# 尝试开发一种新的扩展方法,c#,linq,entity-framework,linq-to-entities,lambda,C#,Linq,Entity Framework,Linq To Entities,Lambda,我正在使用实体框架,并开发了此扩展方法: public static IQueryable<TResult> Like<TResult>(this IQueryable<TResult> query, Expression<Func<TResult, string>> field, string value) { var expression = Expression.Lambda<Func<TResult, bo

我正在使用实体框架,并开发了此扩展方法:

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);
}
现在我需要以编程方式调用此扩展方法:

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);
}
public static IQueryable SearchInText(此IQueryable源,字符串textToFind)
{
//集田
PropertyInfo[]propertiesInfo=source.ElementType.GetProperties();
列表字段=新列表();
foreach(PropertyInfo PropertyInfo中的PropertyInfo)
{
如果(
(propertyInfo.PropertyType==typeof(字符串))||
(propertyInfo.PropertyType==typeof(int))||
(propertyInfo.PropertyType==类型(长))||
(propertyInfo.PropertyType==typeof(字节))||
(propertyInfo.PropertyType==typeof(短))
)
{
fields.Add(propertyInfo.Name);
}
}
ParameterExpression参数=Expression.parameter(typeof(TSource),source.ElementType.Name);
Expression=Expression.Lambda(Expression.Property(参数,typeof(TSource).GetProperty(字段[0])),参数);
表达式字段=表达式.Lambda(表达式,参数);
返回source.Like(字段,textToFind);
}
现在这个代码不起作用了! 我需要了解如何声明类似扩展方法的“字段”

Expression<Func<TSource, string>> field = Expression.Lambda<Func<TSource, string>>(expression, parameter);
Expression field=Expression.Lambda(表达式,参数);

在运行时,我收到以下错误:不可能的实用程序un'espressine di tipo'System.Func`2[TestMdf.Equipment,System.String]'per un tipo restituto'System.String'

我假设您的第二个代码片段只是一个截断的示例-如果您真的这样做了,那么结果将是不可预测的,因为您使用的是反射返回的第一个属性,它可以在程序运行之间更改

如果你说“这起作用了”,然后描述发生了什么,“这没起作用”,然后描述如何判断它不起作用(编译器错误?运行时错误?异常消息?),你会得到更好的答案

首先,你知道吗?它允许您在运行时才决定如何构造查询,并可能为您解决许多问题

但假设这是一个学习练习

您的
Like
扩展方法采用一个表达式(调用者通常应该将其写成lambda,因为这就是这些内容的全部要点)。该表达式将转换查询结果集中的“记录”,并返回字符串值(可能是从记录中存储的数据中选择)。该方法还接受一个值字符串

但它随后(手动)构造自己的谓词,调用
字段
lambda主体上的
Contains
方法

我想这应该行得通,因为lambda的结果是一个字符串。然而,我不明白你为什么要这么做。有什么问题吗

var result = from e in context.es
             where e.Field.Contains("xxx"))
             select e

现在我找到了问题的部分解决方案:

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);

    var property = typeof(TSource).GetProperty(fields[0]);
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        var constantValue = Expression.Constant(textToFind);
    var equality = Expression.Call(Expression.Call(Expression.Property(parameter,     property), "ToUpper", null, null), typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(textToFind.ToUpper()));

    return source.Where(Expression.Lambda<Func<TSource, bool>>(equality, parameter));
}

一些想法?

这是我的第一个版本:

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));

}
public static IQueryable SearchInText(此IQueryable源,字符串textToFind)
{
如果(textToFind.Trim()=“”)
{
返回源;
}
字符串[]textToFindList=textToFind.Replace(“”,““””).Split(“”);
//集田
PropertyInfo[]propertiesInfo=source.ElementType.GetProperties();
列表字段列表=新列表();
foreach(PropertyInfo PropertyInfo中的PropertyInfo)
{
如果(
(propertyInfo.PropertyType==typeof(字符串))||
(propertyInfo.PropertyType==typeof(int))||
(propertyInfo.PropertyType==类型(长))||
(propertyInfo.PropertyType==typeof(字节))||
(propertyInfo.PropertyType==typeof(短))
)
{
fieldList.Add(propertyInfo.Name);
}
}
ParameterExpression参数=Expression.parameter(typeof(TSource),source.ElementType.Name);
MethodInfo concatMethod=typeof(String).GetMethod(“Concat”,新类型[]{typeof(String),typeof(String)});
var spaceExpression=Expression.Constant(“”);
var concatenatedField=BinaryExpression.Add(spaceExpression,Expression.MakeMemberAccess(参数,typeof(TSource).GetProperty(fieldList[0])),concatMethod);
for(int i=1;i

我将修改以管理一些规则,如“短语”+和-operator。

我对您的第二个扩展方法有点困惑。循环遍历元素上的所有PropertyInfo,将它们添加到字段集合中,然后只选择第一个字段
" " + fields[0] + " " + ... fields[n]
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));

}