如何在lambda表达式中按字符串属性名进行选择查询?

时间:2014-10-20 06:53:14

标签: c# select lambda expression

我想使用lambda select,

进行查询

如下所示:

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

属性名称需要以字符串形式发送, 我不知道如何使用,我已经把它作为一个例子。 有可能吗?

编辑:

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

我不知道通用列表的类型,我有属性名称,如&#34;姓名&#34;,&#34;姓氏&#34;

我希望如下:

Result :

A B
C D
E F
G H

4 个答案:

答案 0 :(得分:3)

以下代码段显示了2个案例。一个过滤列表,另一个创建一个新的匿名对象列表,只有Name和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));

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

接口

如果您有权访问相关类型,并且您始终想要访问相同的属性,那么最好的选择是使类型实现相同的接口:

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

这将保留类型安全性并启用如下的查询:

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

如果出于某种原因,您无法更改原始类型,则还有两个选项。

反射

第一个是反思。这是Mez的答案,我只是用以前的解决方案中的匿名类型来改写它(不确定你需要什么):

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

动态

第二个使用动态:

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

有了这个,下面的代码:

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

将产生预期的输出:

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

我相信你可以摆弄它并达到你想要实现的目标。