Reputation: 77906
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.
Upvotes: 2
Views: 2718
Reputation: 36523
(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.
Upvotes: 5
Reputation: 1208
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.
Upvotes: 4