2016-08-05 2 views
2

У меня есть имя свойства класса как строковая переменная и вы хотите использовать это в запросе LINQ. Ниже пример:Использовать строковую переменную в выражении LINQ lambda

public class Demo 
{ 
    public string prop1 {get; set;} 
    public string prop2 {get; set;} 
    public string prop3 {get; set;} 
} 

Я могу это сделать

var data = db.Single<Demo>(d => d.prop1 == "value"); 

Но не знаю, что это свойство во время выполнения и получить этот строковый параметр как

string propname = "prop2"; 

Есть ли возможность использовать это в лямбда-выражении d => d.propname == "value"? Я не уверен, что это может быть и логически не представляется возможным. поэтому подумал о том, чтобы задать вопрос и посмотреть, есть ли способ. Пожалуйста, предложите.

Обратите внимание, что звонок Single() происходит через MongoDB C# Driver и, таким образом, не будет уверен, будет ли отражение работать.

+3

Возможно, это работа для выражения [Linq Expression] (https://msdn.microsoft.com/fr-fr/library/system.linq.expressions (v = vs.110) .aspx) (не следует путать с лямбда-выражением); скомпилировав правую «вещь» на лету с учетом параметра. – Sehnsucht

+0

Как для владельца ответа, так и для того, чтобы указать, что он установлен на драйвер MongoDB C#. Извините за это, но независимо от того, что оба ответа являются хорошими и действительными. – Rahul

+0

@ Rahul вы пробовали? – squill25

ответ

4

(Это был оригинальный при условии, прежде чем понял, что отражение не помогло бы в этом конкретном случае см редактирования ниже для обновленного ответа.)

Если вы не возражаете, используя отражение, вы можете сделать:

var data = db.Single<Demo>(d => "value" == (string)typeof(Demo).GetProperty(propname).GetValue(d)); 

EDIT

Как и другие имеют час в комментариях, чтобы сделать эту работу с MongoDB, вам нужно будет создать выражение «вручную».

Итак, если я возьму следующее заявление:

var data = db.Single<Demo>(d => d.prop1 == "value"); 

Я считаю, что следующие должны быть эквивалентны, но построение лямбда-выражение вручную:

string propname = "prop1"; // you can now change this to any valid property name. 

var parameterExpresion = Expression.Parameter(typeof(Demo), "d"); 
var binaryExpression = Expression.Equal(
    Expression.Property(parameterExpresion, propname), 
    Expression.Constant("value")); 
var lambda = Expression.Lambda<Func<Demo, bool>>(binaryExpression, parameterExpresion); 

var data = db.Single<Demo>(lambda); 

... за исключением того, что теперь , вы должны иметь возможность изменить значение propname на любое допустимое имя свойства, и оно должно просто работать.

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

+0

Спасибо sstan, хотя не уверен, будет ли отражение работать, поскольку вызов «Single» происходит на «MongoDB C# Driver», но стоит попробовать. – Rahul

+0

Вы правы. Я не думаю, что это сработает. – sstan

+0

не уверен и не могу сказать, если не пробовал, но тем не менее хороший ответ. – Rahul

4

EDIT: Этот ответ не работает для MongoDB. См. Ответ @ sstan.

Как @sstan сказал, вы можете использовать отражение:

var property = typeof(Demo).GetProperty("propertyName"); 
var data = db.Single<Demo>(d => (string)property.GetValue(d) == "value"); 

property является объектом типа PropertyInfo, который имеет метод GetValue. Этот метод принимает объект и возвращает указанное свойство объекта.

Кроме того, в примере @ sstan будет вызываться typeof(Demo).GetProperty("propertyName") для каждого объекта, который (в зависимости от размера вашего db) может составлять миллионы. Лучше получить его один раз заранее и повторно использовать.

+0

Вы протестировали это, как это будет работать с деревом выражений? –

+0

@ johnny5 нет У меня нет, я отправил ответ до появления проблемы MongoDB. – squill25

+0

По крайней мере, я протестировал его, и он сработал. – Andrew

Смежные вопросы