2

I have a class property name as string variable and want to use that in LINQ query. Below example:

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

I can do this

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

But don't know what's the property is at runtime and getting that string parameter like

string propname = "prop2";

Is there any possibility to use that in lambda expression d => d.propname == "value"? I am not sure it can be and logically doesn't seem possible. so thought of posting a question and see if there is a way. Please suggest.

To Note, that Single() call is happening over MongoDB C# Driver and thus not sure whether reflection would work.

7
  • 3
    Could probably be a job for a Linq Expression (not to be confused with a lambda expression) ; compiling the right "thing" on the fly given the parameter. Commented Aug 5, 2016 at 23:40
  • To both answer owner, missed to point that it's on MongoDB C# driver. Sorry for that but irrespective of that both the answers are good and valid. Commented Aug 5, 2016 at 23:53
  • @Rahul have you tried it though? Commented Aug 5, 2016 at 23:55
  • 1
    @Ignaus, on my way and so can't say for sure. Commented Aug 5, 2016 at 23:56
  • @Sehnsucht, thanks for pointing that but unfortunately that's a non-English which I don't understand. But got what you are saying. Commented Aug 6, 2016 at 0:01

2 Answers 2

5

(This was the original provided before realizing that reflection wouldn't help in this particular case. See edit below for updated answer)

If you don't mind using reflection, you could do:

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

EDIT

As others have hinted at in the comments, to make this work with MongoDB, you'll have to build the expression "by hand".

So, if I take the following statement:

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

I believe that the following should be equivalent, but building the lambda expression by hand:

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

... except that now, you should be able to change the value of propname to any valid property name, and it should just work.

Looking at how verbose the code gets when building lambdas manually really helps me appreciate all the compiler magic that happens without us ever noticing.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks sstan, though not sure whether reflection would work since the Single call is happening on MongoDB C# Driver but worth giving a try.
not sure and can't say unless tried but none the less nice answer.
@Rahul you should add that MongoDB part with appropriate tag in your question
I edited my answer to provide a solution that should work with MongoDB.
This answer deserves more vote and yes this is the way went ahead. as doubted reflection didn't helped. Appreciate your effort for putting the answer. I would also suggest not to remove your first answer, include that as well and append this modified one as EDIT. Cool mate ... will return your help back on your question someday.
4

EDIT: this answer doesn't work for MongoDB. See @sstan's answer.

As @sstan said, you can use reflection:

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

property is an object of type PropertyInfo which has a method GetValue. This method takes an object and returns that object's specified property.

Also, in @sstan's example, typeof(Demo).GetProperty("propertyName") will be called for each object which (depending on the size of your db) could be millions. It is better to get it once beforehand and reuse it.

4 Comments

Have you tested this, how this will work with out an expression tree?
@johnny5 no I haven't, I posted the answer before the MongoDB issue came up.
This shouldn't work on entity framework either db implies that it is an orm. Your answer should probably work if you convert it to an expression, thou. Please make the edits
@johnny5 sstan made a great answer already, mine should now be disregarded

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.