Свойство доступа Linq по переменной

Скажем, у меня есть класс вроде:

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

person Rafael Herscovici    schedule 07.01.2012    source источник


Ответы (5)


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

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);
person L.B    schedule 07.01.2012

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

object GetProperty(Foo f, string propertyName) {
  var type = typeof(Foo);
  var propInfo = type.GetProperty(propertyName);
  return propInfo.GetValue(f, null);
}
person JaredPar    schedule 07.01.2012

Если вам нужно динамически составлять запросы на лету, вы можете использовать динамический запрос LINQ. библиотека, образец от 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, часть 1: Использование библиотеки динамических запросов LINQ (Не думаю, что когда-либо была часть 2...)

Примечание. Вам необходимо скомпилировать образец кода от Microsoft и указать ссылку на созданную сборку, или вы можете включить этот код в свой собственный проект.

person Michiel van Oosterhout    schedule 07.01.2012
comment
хм, любая причина, по которой он не является частью стандартного .net framework, выглядит заманчиво.. - person Surjit Samra; 07.01.2012
comment
@SurjitSamra Во время первого выпуска LINQ (Visual Studio 2008, C# 3.0) Microsoft написала множество примеров, чтобы помочь всем понять возможности LINQ. Это был лишь один из тех примеров, которые сами по себе могут быть очень полезными, но могут быть слишком ограниченными, чтобы быть частью структуры. - person Michiel van Oosterhout; 07.01.2012
comment
Если я окажусь в этой ситуации, то, честно говоря, я предпочту ответ ЛБ. - person Surjit Samra; 08.01.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» прямо в предложении 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();
person MikeKulls    schedule 06.09.2012

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

 var query =  db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
            OrderBy("CompanyName").
            Select("New(CompanyName as Name, Phone)"); 
person kunkun kurniawan    schedule 07.01.2012
comment
Зачем ты дал ссылку на лицензионное соглашение? - person Cody Gray; 07.01.2012