LINQ按名称选择属性

Wiz*_*mer 6 c# linq expression

我试图在LINQ select语句中使用变量.

这是我现在正在做的一个例子.

using System;
using System.Collections.Generic;
using System.Linq;
using Faker;

namespace ConsoleTesting
{
internal class Program
{
    private static void Main(string[] args)
    {
        List<Person> listOfPersons = new List<Person>
        {
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person(),
            new Person()
        };

        var firstNames = Person.GetListOfAFirstNames(listOfPersons);

        foreach (var item in listOfPersons)
        {
            Console.WriteLine(item);
        }

        Console.WriteLine();
        Console.ReadKey();
    }


    public class Person
    {
        public string City { get; set; }
        public string CountryName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public Person()
        {
            FirstName = NameFaker.Name();
            LastName = NameFaker.LastName();
            City = LocationFaker.City();
            CountryName = LocationFaker.Country();
        }

        public static List<string> GetListOfAFirstNames(IEnumerable<Person> listOfPersons)
        {
            return listOfPersons.Select(x => x.FirstName).Distinct().OrderBy(x => x).ToList();
        }

        public static List<string> GetListOfCities(IEnumerable<Person> listOfPersons)
        {
            return listOfPersons.Select(x => x.FirstName).Distinct().OrderBy(x => x).ToList();
        }

        public static List<string> GetListOfCountries(IEnumerable<Person> listOfPersons)
        {
            return listOfPersons.Select(x => x.FirstName).Distinct().OrderBy(x => x).ToList();
        }

        public static List<string> GetListOfLastNames(IEnumerable<Person> listOfPersons)
        {
            return listOfPersons.Select(x => x.FirstName).Distinct().OrderBy(x => x).ToList();
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

我有一些非常不干的代码与GetListOf ...方法

我觉得我应该可以做这样的事情

public static List<string> GetListOfProperty(
IEnumerable<Person> listOfPersons, string property)
        {
            return listOfPersons.Select(x =>x.property).Distinct().OrderBy(x=> x).ToList();
        }
Run Code Online (Sandbox Code Playgroud)

但这不是虚拟代码.我认为关键在于创造一个功能

如果这就是答案我该怎么做?

这是使用refelection的第二次尝试但是这也是不行的.

        public static List<string> GetListOfProperty(IEnumerable<Person> 
listOfPersons, string property)
        {
            Person person = new Person();
            Type t = person.GetType();
            PropertyInfo prop = t.GetProperty(property);
            return listOfPersons.Select(prop).Distinct().OrderBy(x => 
x).ToList();
}
Run Code Online (Sandbox Code Playgroud)

我认为反射可能是一个DeadEnd /红鲱鱼,但我想我还是会展示我的作品.

注意实际上简化了示例代码,它用于通过AJAX 填充数据列表以创建自动完成体验.该对象具有20多个属性,我可以通过编写20多种方法来完成,但我觉得应该有一种干燥的方法来完成它.同样制作这个方法也会清理我的控制器动作.

题:

鉴于代码的第一部分有一种方法将这些类似的方法抽象为单个方法,请将一些对象传递给select语句???

感谢您的时间.

Jam*_*aix 6

从你的例子来看,我认为你想要的是这样的:

public static List<string> GetListOfProperty(IEnumerable<Person> 
    listOfPersons, string property)
{
    Type t = typeof(Person);         
    PropertyInfo prop = t.GetProperty(property);
    return listOfPersons
        .Select(person => (string)prop.GetValue(person))
        .Distinct()
        .OrderBy(x => x)
        .ToList();
Run Code Online (Sandbox Code Playgroud)

}

typeof是 C# 中的内置运算符,您可以将类型名称“传递”给它,它将返回相应的实例Type。它在编译时而不是运行时工作,因此它不像普通函数那样工作。

PropertyInfo有一个GetValue采用对象参数的方法。对象是要从中获取属性值的类型的实例。如果您尝试定位某个static属性,请使用null该参数。

GetValue返回一个object,您必须将其转换为实际类型。

person => (string)prop.GetValue(person)是一个lambda表达式,其签名如下:

string Foo(Person person) { ... }

如果您希望它适用于任何类型的属性,请将其设为通用而不是硬编码string

public static List<T> GetListOfProperty<T>(IEnumerable<Person> 
    listOfPersons, string property)
{
    Type t = typeof(Person);         
    PropertyInfo prop = t.GetProperty(property);
    return listOfPersons
        .Select(person => (T)prop.GetValue(person))
        .Distinct()
        .OrderBy(x => x)
        .ToList();
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 5

您将必须建立选择

.Select(x =>x.property).
Run Code Online (Sandbox Code Playgroud)

用手。幸运的是,这并不是一个棘手的问题,因为您希望它始终是同一类型(string),因此:

var x = Expression.Parameter(typeof(Person), "x");
var body = Expression.PropertyOrField(x, property);
var lambda = Expression.Lambda<Func<Person,string>>(body, x);
Run Code Online (Sandbox Code Playgroud)

然后Select上面变成:

.Select(lambda).
Run Code Online (Sandbox Code Playgroud)

(基于的LINQ IQueryable<T>)或

.Select(lambda.Compile()).
Run Code Online (Sandbox Code Playgroud)

(基于的LINQ IEnumerable<T>)。

请注意,您可以采取任何措施来缓存最终表单property