Создание динамических запросов LINQ на основе значения поля со списком

У меня есть поле со списком в Silverlight. Он имеет набор значений, созданных на основе свойств одного из моих объектов LINQ-to-SQL (например, имени, адреса, возраста и т. Д.). Я хотел бы отфильтровать свои результаты на основе значения, выбранного в поле со списком.

Пример. Скажем, я хочу, чтобы у всех была фамилия Смит. Я бы выбрал «Фамилия» из раскрывающегося списка и ввел бы смит в текстовое поле. Обычно я бы написал LINQ-запрос, похожий на ...

var query = from p в коллекции
где p.LastName == textbox.Text
select p;

Можно ли определять свойство динамически, возможно, используя Reflection? Что-то типа

var query = from p в коллекции
где p. (DropDownValue) == textbox.Text
select p;


person Steve G.    schedule 30.01.2009    source источник


Ответы (3)


Предполагая:

public class Person
{
    public string LastName { get; set; }
}

IQueryable<Person> collection;

Ваш запрос:

var query =
    from p in collection
    where p.LastName == textBox.Text
    select p;

означает то же, что и:

var query = collection.Where(p => p.LastName == textBox.Text);

который компилятор переводит из метода расширения в:

var query = Queryable.Where(collection, p => p.LastName == textBox.Text);

Второй параметр Queryable.Where - это Expression<Func<Person, bool>>. Компилятор понимает тип Expression<> и генерирует код для построения дерева выражений, представляющего лямбда:

using System.Linq.Expressions;

var query = Queryable.Where(
    collection,
    Expression.Lambda<Func<Person, bool>>(
        Expression.Equal(
            Expression.MakeMemberAccess(
                Expression.Parameter(typeof(Person), "p"),
                typeof(Person).GetProperty("LastName")),
            Expression.MakeMemberAccess(
                Expression.Constant(textBox),
                typeof(TextBox).GetProperty("Text"))),
        Expression.Parameter(typeof(Person), "p"));

Вот что означает синтаксис запроса.

Вы можете сами вызывать эти методы. Чтобы изменить сравниваемое свойство, замените это:

typeof(Person).GetProperty("LastName")

с участием:

typeof(Person).GetProperty(dropDown.SelectedValue);
person Bryan Watts    schedule 30.01.2009

У Скотта Гатри есть небольшая серия статей о динамически построенных запросах LINQ to SQL:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Это простой способ ... есть другой способ, который немного сложнее:

http://www.albahari.com/nutshell/predicatebuilder.aspx

person Kev    schedule 30.01.2009
comment
Эти статьи идеально подходят, если вы работаете с приложениями ASP.NET, полезно знать, спасибо за это, к сожалению, с Silverlight, System.Windows.Threading не поддерживает некоторые методы, используемые в динамической библиотеке LINQ. - person Steve G.; 02.02.2009
comment
Ах ... тег Silverlight был в моем слепом пятне. - person Kev; 02.02.2009

Вы также можете использовать созданную мной библиотеку: http://tomasp.net/blog/dynamic-linq-queries.aspx. Вы должны сохранить свойства в ComboBox как лямбда-выражения, а затем просто написать:

var f = (Expression<Func<Product, string>>)comboBox.SelectedValue;
var query =
    from p in collection
    where f.Expand(textBox.Text)
    select p;
person Tomas Petricek    schedule 12.02.2009