0

所以,我使用 MVC 并且我正在使用一个名为 DataTable 的 JS 库来显示数据。好吧,我正在使用来自服务器的 AJAX 响应将数据提供给表。因为我会经常使用 DataTable,所以我决定创建一个模型,让我可以快速创建一个实例并将数据反馈给客户端。我已经解决了所有这些问题,但是,我在搜索方面遇到了一个问题。我正在使用在运行时Expression.Call()构建一个查询,以便从我的数据库中收集我的数据。我正在使用泛型,因为我使用 DataTable 显示了许多不同的模型,这是为了最大限度地减少我的代码行而创建的。

好吧,有时调用将需要大约一秒钟才能完成并返回给客户端。不可怕,但我相信这次应该有办法改进。我考虑过将我生成的方法存储Expression.Call()在一个变量中,然后再调用它。唯一的问题是,一旦我使用了缓存的表达式,就没有定义我的变量。我必须在开始时为我的方法提供一个参数,这导致了问题。

此外,我对使用 System.Reflection 和泛型还很陌生。如果有更好的使用方法,请链接到文章。

错误是关于变量 'item' 存在但未在此上下文中定义的内容。

private static readonly var CachedSearchQuery = new Dictionary<string, MethodCallExpression>();
private Expression<Func<T, bool>> GenerateSearchValues()
            {
                if (search == null || search.value == null)
                    return null;
            Expression<Func<T, bool>> body = null;
            ParameterExpression param = Expression.Parameter(typeof(T), "item");
            columns.ForEach(c =>
            {
                if (c.searchable)
                {
                    var prop = Expression.PropertyOrField(param, c.data);
                    var containMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                    var toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes);
                    var toString = typeof(string).GetMethod("ToString", Type.EmptyTypes);

                    var cont = Expression.Constant(search.value, typeof(string));
                    Expression<Func<T, bool>> containExpr = null;

                    if(!CachedSearchQuery.Contains(c.data)) {
                        try
                        {
                            CachedSearchQuery[c.data] = Expression.Call(prop, toLowerMethod);
                            containExpr = Expression.Lambda<Func<T, bool>> (
                                Expression.Call(
                                    CachedSearchQuery[c.data],
                                    containMethod,
                                    cont),
                                param);
                        }
                        catch/*(ArgumentException e)*/
                        {
                            toString = typeof(object).GetMethod("ToString", Type.EmptyTypes);
                            CachedSearchQuery[c.data] = 
                                        Expression.Call(
                                            Expression.Call(prop, toLowerMethod),
                                        toString);
                            containExpr = Expression.Lambda<Func<T, bool>>(
                                Expression.Call(
                                    CachedSearchQuery[c.data],
                                        containMethod,
                                        cont),
                                    param);
                        }
                    }
                    else
                    {
                        containExpr = 
                            Expression.Lambda<Func<T, bool>>(
                                Expression.Call(
                                    CachedSearchQuery[c.data],
                                        containMethod,
                                        cont),
                                    param);
                    }

                    if (containExpr == null)
                        return;
                    if (body == null)
                        body = containExpr;
                    else
                    {
                        body = Expression.Lambda<Func<T, bool>>
                        (
                            Expression.Or(
                                body, 
                                Expression.Invoke(
                                    containExpr, 
                                    body.Parameters.Cast<Expression>()
                                )
                            ),
                        body.Parameters);
                    }
                }
            });

            return body;
        }
4

0 回答 0