Reputation: 19903
I have this object :
public class MyObject
{
public int Id { get; set; }
public string FieldA { get; set; }
public string FieldB { get; set; }
public string FieldC { get; set; }
public string FieldD { get; set; }
}
I have an IList<> of this object :
IList<MyObject> MyListObject = new List<MyObject>();
I do a Linq query on it :
var result = (from p in MyListObject where p.FieldC == "Test" select p.FieldA);
In this case, I return "p.FieldA" but sometimes I need to return "p.FieldB". I'd like put the name of the field (FieldA or FieldB) in a variable like this
var myvar = "FieldB"
var result = (from p in MyListObject where p.FieldC == "Test" select p.????);
How use myvar content (FieldB) as field name in the Linq query ?
Thanks,
Upvotes: 1
Views: 8242
Reputation: 5871
You can use reflection to get the value of a property based on its name. This will allow you to select any property from you class.
Here's an example using an extension method on the MyObject class:
public static string GetPropertyValue(this MyObject myObj, string propertyName)
{
var propInfo = typeof(MyObject).GetProperty(propertyName);
if (propInfo != null)
{
return propInfo.GetValue(myObj, null).ToString();
}
else
{
return string.Empty;
}
}
Your LINQ query would then look like this:
string propName = "FieldB";
var result = from m in myList where m.FieldC == "Test" select m.GetPropertyValue(propName);
Upvotes: 0
Reputation: 7846
If you want it to work with IQueryable, you could do something like this:
var filtered = MyListObject.Where(p => p.FieldA == "Test");
var results = condition ? filtered.Select(p => p.FieldA) : filtered.Select(p => p.FieldB);
which can be refactored to:
Expression<Func<MyObject,string>> selector;
switch(condition)
{
case "FieldA": selector = o => o.FieldA; break;
case "FieldB": selector = o => o.FieldB; break;
// other cases here
default: throw new NotImplmentedException();
}
var results = MyListObject.Where(p => p.FieldA == "Test").Select(selector);
Upvotes: 0
Reputation: 52518
If your method itself knows it has to choose between FieldA and FieldB you can use:
var whatField = "FieldA";
var result = (from p in MyListObject
where p.FieldA == "Test"
select (whatField == FieldA ? p.FieldA : p.FieldB));
If you have more as 2 options, I would choose to pass a lambda;
Func<MyObject, object> fieldGetter;
// Option A, switch
switch (whatField) {
case "FieldA": fieldGetter = o => o.FieldA; break;
case "FieldB": fieldGetter = o => o.FieldB; break;
// More options
}
// Option B using reflection:
var t = typeof(MyObject);
var prop = t.GetProperty(whatField);
fieldGetter = o => prop.GetValue(o, null);
// Linq then looks like
var result = (from p in MyListObject
where p.FieldA == "Test"
select fieldGetter(p));
The advantage of using the lambda is, you can split your logic, what field and how to query. And you can even make it work for different types:
IEnumerable<T> Query<T>(IQueryable<MyObject> MyListObject, Func<MyObject, T> fieldGetter) {
return result = (from p in MyListObject
where p.FieldA == "Test"
select fieldGetter(p));
}
// call using:
var result = Query(MyListObject, o => o.FieldA);
Upvotes: 5
Reputation: 4918
Is FieldA and FieldB the same type?
If yes then you can do something like this:
var result = (from p in MyListObject where p.FieldA == "Test"
select (condition ? p.FieldA : p.FieldB));
Upvotes: 0