System.Reflection: сохранение выражения для последующего использования - PullRequest
0 голосов
/ 10 июля 2019

Итак, я использую MVC и использую библиотеку JS с именем DataTable для отображения данных. Что ж, я передаю данные в таблицу, используя ответ AJAX с сервера. Поскольку я буду часто использовать DataTable, я решил создать модель, которая позволит мне быстро создать экземпляр и передать данные клиенту. У меня все это решено, однако у меня есть одна проблема с поиском. Я использую Expression.Call() для создания запроса в RunTime для сбора данных из моей базы данных. Я работаю с дженериками, потому что у меня есть много разных моделей, которые я отображаю с помощью 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;
        }
...