1

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,

4 Answers 4

5

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);
Sign up to request clarification or add additional context in comments.

4 Comments

This will not work because your fieldGetter is Func<MyObject,object>, this will work only if your fieldGetter is of type Expression<Func<MyObject,object>>, you will get an error that Invoke not supported while running it. And you will have to combine to linq expressions.
Option 2 is a good answer as it allows you to add more field selection by adding more entries to the switch.
@Akash Kava, for LINQ to Objects it would work. The reflection does not work on the DB server anyway, so I think it is safer to not use the Expression syntax. Correct me if I'm wrong.
Yes you are right, my bad, I thought he will be querying against DB.
0

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

2 Comments

Same type yes. Your solution is ok, for 2 field but I can have 3 field in my class. I'd like an another solution than a switch
But how would you like to choose appropriate field? There has to be some logic. You can of course use a method in select, but still in this method there will be if or switch (or any other solution to choose good field)
0

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

Comments

0

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

Comments

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.