Linq свойство доступа по переменной - PullRequest
7 голосов
/ 07 января 2012

Допустим, у меня есть такой класс:

public class Foo
{
    public string Title {get;set;}
}

Теперь давайте предположим, что у меня есть public List<Foo> myList, который я хочу отфильтровать по Linq следующим образом:

var x = myList.Where(f => f.Title == myValue);

До сих пор все хорошо и понятно.

Но как получить доступ к свойству по переменной? Что-то вроде:

string myProperty = "Title";

var x = myList.Where(f => f.myProperty == myValue);

Ответы [ 5 ]

15 голосов
/ 07 января 2012

Вы можете написать метод расширения

public static class MyExtensions
{
    public static object GetProperty<T>(this T obj, string name) where T : class
    {
        Type t = typeof(T);
        return t.GetProperty(name).GetValue(obj, null);
    }
}

и используйте его вот так

var x = myList.Where(f => f.GetProperty("Title") == myValue);
3 голосов
/ 07 января 2012

Это не тот тип ситуации, для которого используется LINQ. LINQ - свободный интерфейс для управления коллекциями. Доступ к членам через текстовое представление осуществляется с помощью отражения.

object GetProperty(Foo f, string propertyName) {
  var type = typeof(Foo);
  var propInfo = type.GetProperty(propertyName);
  return propInfo.GetValue(f, null);
}
2 голосов
/ 06 сентября 2012

Я знаю, что это старая тема, но здесь есть еще один способ сделать это. Это имеет преимущество в том, что значительно быстрее, если вам нужно сделать это в цикле. Я преобразовал результат из "func" в объект, чтобы сделать его более универсальным.

        var p = Expression.Parameter(typeof(string));
        var prop = Expression.Property(p, "Length");
        var con = Expression.Convert(prop, typeof(object));
        var exp = Expression.Lambda(con, p);
        var func = (Func<string, object>)exp.Compile();

        var obj = "ABC";
        int len = (int)func(obj);

В исходном вопросе код использовался внутри linq, поэтому скорость могла быть хорошей. Было бы возможно использовать "func" direct в предложении where, если бы он был построен правильно, например,

        class ABC
        {
            public string Name { get; set; }
        }

        var p = Expression.Parameter(typeof(ABC));
        var prop = Expression.Property(p, "Name");
        var body = Expression.Equal(prop, Expression.Constant("Bob"));
        var exp = Expression.Lambda(body, p);
        var func = (Func<ABC, bool>)exp.Compile();

        ABC[] items = "Fred,Bob,Mary,Jane,Bob".Split(',').Select(s => new ABC() { Name = s }).ToArray();
        ABC[] bobs = items.Where(func).ToArray();
2 голосов
/ 07 января 2012

Если вам нужно динамически составлять запросы на лету, вы можете использовать библиотеку LINQ Dynamic Query , пример от Microsoft:

В этом примере показан метод составления операторов LINQ на летать, динамически, во время выполнения.

Ссылка на библиотеку в вашем коде:

using System.Linq.Dynamic;

Ваш запрос будет выглядеть так:

// You can use a string as the argument for the Where method
// meaning you can compose this string dynamically
string myProperty = "Title";
var x = myList.Where(myProperty + " = " + myValue);

Также возможно использовать заполнитель в строке запроса, что улучшает читабельность (в некоторой степени):

var x = myList.Where("@0 = @1", myProperty, myValue);

См. Также этот пост от Скотта Гатри: Dynamic LINQ Part 1: Использование библиотеки динамических запросов LINQ ( Не думаю, что когда-либо была часть 2 ... )

Примечание: вы должны скомпилировать пример кода от Microsoft и ссылаться на встроенную сборку, или вы можете включить код в ваш собственный проект.

0 голосов
/ 07 января 2012

вы не можете использовать linq динамический запрос от Microsoft вот пример кода

 var query =  db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
            OrderBy("CompanyName").
            Select("New(CompanyName as Name, Phone)"); 
...