Errore di riferimento dell'oggetto nell'assembly DynamicMethods ospitato in modo anonimo

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

Domanda

Ho il seguente codice in cui ho bisogno di implementare la ricerca full-text su un elenco di oggetti. Sono riuscito a farlo funzionare in un'applicazione console. Il problema è quando comincio a utilizzare questo nell'applicazione WebAPI. Viene visualizzato un messaggio di errore che Object reference not set to an instance of an object. e il Source è Anonymously Hosted DynamicMethods Assembly . Sembra che alcune proprietà del Type T siano nulle e quando si accede l'errore si apre. Qualcuno può dirmi se la mia comprensione è corretta o meno e se è corretta allora puoi aiutarmi anche a capire come eliminare le proprietà nulle?

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

Risposta accettata

Ok Ragazzi, l'ho capito. Ecco il codice nel caso in cui qualcuno ne avesse bisogno.

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

L'unica parte che è cambiata è il LINQ in cui ottengo due espressioni che ne contengono una per "Contains" e una per "Not (IsNullOrEmpty)" expression andalso'ed.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché