2016-04-06 19 views
0

Örneğin, bir listeyi filtreleyen ve yalnızca Montreal ve New York'ta yaşayan kişileri döndüren bir uzantı yöntemim var. BuGenel Kimligörle İfade Çağrısı veya ifade

public static IQueryable<Tsource> Where<Tsource, Tproperty>(this IQueryable<Tsource> source, Expression<Func<Tsource, Tproperty>> property, IList<int?> accpetedValues) 
     { 
      var propertyName = ((MemberExpression)property.Body).Member.Name; 

      if (propertyName == null) 
       throw new ArgumentException(); 

      if (accpetedValues == null || string.IsNullOrEmpty(propertyName)) 
       return source; 

      var item = Expression.Parameter(typeof(Tsource), "item"); 
      var selector = Expression.PropertyOrField(item, propertyName); 

      var predicate = Expression.Lambda<Func<Tsource, bool>>(Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(Tproperty) }, 
              Expression.Constant(accpetedValues), selector), item); 
      return source.Where(predicate); 
     } 

Let bazı kişi ben de onları almak gerekir, herhangi bir şehir belirtilen olmadığını söylemek gibi

var persons = List<Person>(); 
var acceptedCities = new List{"Montreal", "New York"}; 

myList.Where(p => p.City, acceptedCities); 

uzatma yöntemi arar, o zaman ben bir ameliyathane eklemek benim yöntemini değiştirmek istedi exrpession, ama çalışamam.

var contains = Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(Tproperty) }, 
              Expression.Constant(accpetedValues), selector); 
      var isNull = Expression.Call(typeof(int?), "Equals", new[] { typeof(Tproperty) }, Expression.Constant(null), selector); 
      var orExpression = Expression.Or(contains, isNull); 

      var predicate = Expression.Lambda<Func<Tsource, bool>>(orExpression, item); 
+0

olarak düzelttim? Hepsi sadece 'myList.Where (p => acceptedCities.Contains (p.City))' 'yazıp aynı zamanda eksik bir kişiyi de içermekle aynı şeyi yapmaz. => String.IsNullOrWhiteSpace (p.City) || acceptedCities.Contains (p.City)); '(normal LINQ Nerede işlevini kullanarak) –

+0

Bunun nedeni, IQueryable türünde bir uzantı yöntemidir, bu yüzden yapamıyorum Sadece dediğiniz gibi bir sorgu yazın, çünkü mülkün ismini bilmenin bir yolu yoktur. – JCorriveau

cevap

0

Ben tüm işlev tabi Nerede _why_ açıklayabilir eğer bu cevap daha kolay olabilir bu

public static IQueryable<Tsource> Where<Tsource, Tproperty>(this IQueryable<Tsource> source, Expression<Func<Tsource, Tproperty>> property, IList<int?> accpetedValues) 
     { 
      var propertyName = ((MemberExpression)property.Body).Member.Name; 

      if (propertyName == null) 
       throw new ArgumentException(); 

      if (accpetedValues == null || string.IsNullOrEmpty(propertyName)) 
       return source; 

      var item = Expression.Parameter(typeof(Tsource), "item"); 
      var selector = Expression.PropertyOrField(item, propertyName); 

      var containsExpression = Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(Tproperty) }, 
                Expression.Constant(accpetedValues), selector); 

      var isNullExpression = Expression.Equal(selector, Expression.Constant(null)); 
      var orExpression = Expression.OrElse(isNullExpression, containsExpression); 

      var predicate = Expression.Lambda<Func<Tsource, bool>>(orExpression, item); 
      return source.Where(predicate); 
     }