How to make select query by string property name in lambda expression?

帅比萌擦擦* 提交于 2019-12-23 20:13:58

问题


I would like to make a query by using lambda select,

Like below:

public class Foo{
   public int Id {get;set;}
   public string Name {get;set;}
   public string Surname {get;set;}
}

var list = new List<Foo>();
var temp = list.Select(x=> x("Name"),("Surname"));

The property name needs to be sent as a string, I dont know how to use, I have given it for being a example. is it possible?

Edit:

Foo list :
1  A B
2  C D
3  E F
4  G H

I don't know type of generic list, I have property name such as "Name", "Surname"

I want to be like below:

Result :

A B
C D
E F
G H

回答1:


The following code snippet shows 2 cases. One filtering on the list, and another creating a new list of anonymous objects, having just Name and Surname.

List<Foo> list = new List<Foo>();

var newList = list.Select(x=> new {  
                    AnyName1 = x.Name,
                    AnyName2 = x.Surname
                }); 

var filteredList = list.Select(x => x.Name == "FilteredName" && x.Surname == "FilteredSurname");

var filteredListByLinq = from cust in list
                             where cust.Name == "Name" && cust.Surname == "Surname"
                             select cust;

var filteredByUsingReflection = list.Select(c => c.GetType().GetProperty("Name").GetValue(c, null));



回答2:


Interface

If you have access to the types in question, and if you always want to access the same properties, the best option is to make the types implement the same interface:

public interface INamable
{
  string Name { get; }
  string Surname { get; }
}

public class Foo : INamable
{
  public int Id { get; set; }
  public string Name { get; set; }
  public string Surname { get; set; }
}

This will preserve type safety and enable queries like this one:

public void ExtractUsingInterface<T>(IEnumerable<T> list) where T : INamable
{
  var names = list.Select(o => new { Name = o.Name, Surname = o.Surname });

  foreach (var n in names)
  {
    Console.WriteLine(n.Name + " " + n.Surname);
  }
}

If, for some reason, you can't alter the original type, here are two more options.

Reflection

The first one is reflection. This is Mez's answer, i'll just rephrase it with an anonymous type like in the previous solution (not sure what you need exactly):

public void ExtractUsingReflection<T>(IEnumerable<T> list)
{
  var names = list.Select(o => new
                               {
                                 Name = GetStringValue(o, "Name"),
                                 Surname = GetStringValue(o, "Surname")
                               });
  foreach (var n in names)
  {
    Console.WriteLine(n.Name + " " + n.Surname);
  }
}

private static string GetStringValue<T>(T obj, string propName)
{
  return obj.GetType().GetProperty(propName).GetValue(obj, null) as string;
}

Dynamic

The second uses dynamic:

public void ExtractUsingDynamic(IEnumerable list)
{
  var dynamicList = list.Cast<dynamic>();
  var names = dynamicList.Select(d => new
                                      {
                                        Name = d.Name,
                                        Surname = d.Surname
                                      });
  foreach (var n in names)
  {
    Console.WriteLine(n.Name + " " + n.Surname);
  }
}

With that in place, the following code:

IEnumerable<INamable> list = new List<Foo>
                             {
                               new Foo() {Id = 1, Name = "FooName1", Surname = "FooSurname1"},
                               new Foo() {Id = 2, Name = "FooName2", Surname = "FooSurname2"}
                             };
ExtractUsingInterface(list);
// IEnumerable<object> list... will be fine for both solutions below
ExtractUsingReflection(list);
ExtractUsingDynamic(list);

will produce the expected output:

FooName1 FooSurname1
FooName2 FooSurname2
FooName1 FooSurname1
FooName2 FooSurname2
FooName1 FooSurname1
FooName2 FooSurname2

I'm sure you can fiddle with that and get to what you are trying to achieve.




回答3:


var temp = list.Select(x => x.Name == "Name" && x.Surname == "Surname");



回答4:


var temp = list.Select(x => new {Name = x.Name, Surname = x.Surname});


来源:https://stackoverflow.com/questions/26459953/how-to-make-select-query-by-string-property-name-in-lambda-expression

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!