Error de referencia de objeto en un ensamblado DynamicMethods alojado anónimamente

asp.net-web-api c# expression-trees lambda

Pregunta

Tengo el siguiente código donde necesito implementar la búsqueda de texto completo en una lista de objetos. Logré que esto funcionara en una aplicación de consola. El problema es cuando empiezo a usar esto en la aplicación WebAPI. Recibo un mensaje de error que dice que la Object reference not set to an instance of an object. y la Fuente es Anonymously Hosted DynamicMethods Assembly . Parece que algunas propiedades del Type T son nulas y cuando se accede, aparece el error. ¿Alguien puede decirme si mi entendimiento es correcto o no y si es correcto, entonces también puede ayudarme a descubrir cómo deshacerme de las propiedades nulas?

public static IEnumerable<T> FullTextSearch<T>(this List<T> list, string searchKey)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
            MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
            var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                .Where(p => p.PropertyType == typeof(string));
            Expression orExpressions = null;
            foreach (MethodCallExpression callContainsMethod in 
                               from property in publicProperties
                               let myProperty =Expression.Property(parameter, property.Name)
                               select Expression.Call(myProperty, "Contains", null, Expression.Constant(searchKey)))
            {
                if (orExpressions == null)
                {
                    orExpressions = callContainsMethod;
                }
                else
                {
                    orExpressions = Expression.Or(orExpressions, callContainsMethod);
                }
            }

            IQueryable<T> queryable = list.AsQueryable<T>();
            MethodCallExpression whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { queryable.ElementType },
                queryable.Expression,
                Expression.Lambda<Func<T, bool>>(orExpressions, new ParameterExpression[] { parameter }));
            var results = queryable.Provider.CreateQuery<T>(whereCallExpression).ToList();
            return results;
        }

Respuesta aceptada

Ok chicos, lo he descubierto. Aquí está el código por si alguien lo necesita.

 public static List<T> FullTextSearch<T>(this List<T> list, string searchKey)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
            MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
            var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                .Where(p => p.PropertyType == typeof(string));
            Expression orExpressions = null;

            foreach (var callContainsMethod in from property in publicProperties
                                                                let myProperty = Expression.Property(parameter, property.Name)
                                                                let myExpression = Expression.Call(myProperty, "Contains", null, Expression.Constant(searchKey))
                                                                let myNullExp = Expression.Call(typeof(string), (typeof(string).GetMethod("IsNullOrEmpty")).Name, null, myProperty)
                                                                let myNotExp = Expression.Not(myNullExp)
                                                                select new { myExpression, myNotExp })
            {
                var andAlso = Expression.AndAlso(callContainsMethod.myNotExp, callContainsMethod.myExpression);
                if (orExpressions == null)
                {
                    orExpressions = andAlso;
                }
                else
                {
                    orExpressions = Expression.Or(orExpressions, andAlso);
                }
            }

            IQueryable<T> queryable = list.AsQueryable<T>();
            MethodCallExpression whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { queryable.ElementType },
                queryable.Expression,
                Expression.Lambda<Func<T, bool>>(orExpressions, new ParameterExpression[] { parameter }));
            var results = queryable.Provider.CreateQuery<T>(whereCallExpression).ToList();
            return results;
        }

La única parte que cambió es el LINQ donde obtengo dos Expresiones que contienen una para la expresión "Contiene" y otra para la expresión "No (IsNullOrEmpty)" y también se han hecho.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow