C# LINQ按名称选择属性

C# LINQ按名称选择属性,c#,linq,expression,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> l

我试图在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();
        }
    }
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用假货;
命名空间控制台测试
{
内部课程计划
{
私有静态void Main(字符串[]args)
{
listOfPersons=新列表
{
新人(),
新人(),
新人(),
新人(),
新人(),
新人(),
新人(),
新人(),
新人(),
新人(),
新人()
};
var firstNames=Person.getListofAffirstnames(listOfPersons);
foreach(人员列表中的变量项)
{
控制台写入线(项目);
}
Console.WriteLine();
Console.ReadKey();
}
公共阶层人士
{
公共字符串City{get;set;}
公共字符串CountryName{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公众人士()
{
FirstName=NameFaker.Name();
LastName=NameFaker.LastName();
City=LocationFaker.City();
CountryName=LocationFaker.Country();
}
公共静态列表GetListofAffirstNames(IEnumerable listOfPersons)
{
返回listOfPersons.Select(x=>x.FirstName).Distinct().OrderBy(x=>x.ToList();
}
公共静态列表GetListOfCities(IEnumerable listOfPersons)
{
返回listOfPersons.Select(x=>x.FirstName).Distinct().OrderBy(x=>x.ToList();
}
公共静态列表GetListOfCountries(IEnumerable listOfPersons)
{
返回listOfPersons.Select(x=>x.FirstName).Distinct().OrderBy(x=>x.ToList();
}
公共静态列表GetListOfLastNames(IEnumerable listOfPersons)
{
返回listOfPersons.Select(x=>x.FirstName).Distinct().OrderBy(x=>x.ToList();
}
}
}
}
我有一些非常不枯燥的代码与GetListOf。。。方法

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

public static List<string> GetListOfProperty(
IEnumerable<Person> listOfPersons, string property)
        {
            return listOfPersons.Select(x =>x.property).Distinct().OrderBy(x=> x).ToList();
        }
公共静态列表GetListOfProperty(
IEnumerable listOfPersons,字符串属性)
{
返回listOfPersons.Select(x=>x.property).Distinct().OrderBy(x=>x.ToList();
}
但这不是有效的代码。我认为关键可能与创建Func有关

如果这是答案,我该怎么做

这里是使用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();
}
公共静态列表GetListOfProperty(IEnumerable)
listOfPersons,字符串属性)
{
Person=新人();
类型t=person.GetType();
PropertyInfo prop=t.GetProperty(属性);
返回listOfPersons.Select(prop).Distinct().OrderBy(x=>
x) .ToList();
}
我认为反思可能是一个死胡同/红鲱鱼,但我认为我无论如何都会展示我的工作

注意:示例代码在现实中被简化了,这是用来通过AJAX填充来创建自动完成体验的。这个对象有20多个属性,我可以通过编写20多个方法来完成,但我觉得应该有一个干涸的方法来完成。同样,使用这个方法也会清理我的控制器动作

问题:

给定代码的第一部分,有没有办法将这些类似的方法抽象为一个方法,并将一些对象传递到select语句中


谢谢您的时间。

您必须构建select

.Select(x =>x.property).
用手。幸运的是,这不是一个棘手的问题,因为您希望它始终是相同的类型(
string
),因此:

(对于基于
IQueryable
的LINQ)或

(对于基于
IEnumerable
的LINQ)


请注意,您可以通过
属性
来缓存最终表单。

从您的示例中,我认为您需要的是:

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

你应该能够通过反思来做到这一点。我用的是类似的东西

只需更改您的反射,尝试以下操作:

public static List<string> GetListOfValues(IEnumerable<Person> listOfPersons, string propertyName)
{
    var ret = new List<string>();

    PropertyInfo prop = typeof(Person).GetProperty(propertyName);
    if (prop != null)
        ret = listOfPersons.Select(p => prop.GetValue(p).ToString()).Distinct().OrderBy(x => x).ToList();

    return ret;
}
公共静态列表GetListOfValues(IEnumerable listOfPersons,string propertyName)
{
var ret=新列表();
PropertyInfo prop=typeof(Person).GetProperty(propertyName);
如果(prop!=null)
ret=listOfPersons.Select(p=>prop.GetValue(p.ToString()).Distinct().OrderBy(x=>x.ToList();
返回ret;
}
我希望有帮助

它是基于C#6的


我会尽可能远离反射和硬编码字符串

如何定义一个接受函数选择器T的扩展方法,以便您可以处理字符串属性之外的其他类型

public static List<T> Query<T>(this IEnumerable<Person> instance, Func<Person, T> selector)
{
    return instance
        .Select(selector)
        .Distinct()
        .OrderBy(x => x)
        .ToList();
}
您只需使用类型安全的lambda选择器获取结果

var ids = listOfPersons.Query(p => p.Id);
var firstNames = listOfPersons.Query(p => p.FirstName);
var lastNames = listOfPersons.Query(p => p.LastName);
var cityNames = listOfPersons.Query(p => p.City);
var countryNames = listOfPersons.Query(p => p.CountryName);
编辑

由于您似乎真的需要硬编码字符串作为属性输入,那么省略一些动态性并使用一点确定性如何

public static List<string> Query(this IEnumerable<Person> instance, string property)
{
    switch (property)
    {
        case "ids": return instance.Query(p => p.Id.ToString());
        case "firstName": return instance.Query(p => p.FirstName);
        case "lastName": return instance.Query(p => p.LastName);
        case "countryName": return instance.Query(p => p.CountryName);
        case "cityName": return instance.Query(p => p.City);
        default: throw new Exception($"{property} is not supported");
    }
}

你也可以用这个。对我有用

public static class ObjectReflectionExtensions
{
    public static  object GetValueByName<T>(this T thisObject,  string propertyName)
    {
        PropertyInfo prop = typeof(T).GetProperty(propertyName);
        return prop.GetValue(thisObject);

    }
}
公共静态类ObjectReflectionExtensions
{
公共静态对象GetValueByName(此对象为thisObject,字符串propertyName)
{
PropertyInfo prop=typeof(T).GetProperty(propertyName);
返回prop.GetValue(thisObject);
}
}
像这样打电话

public static List<string> GetListOfProperty(IEnumerable<Person> listOfPersons, string propertyName)
    {
        return listOfPersons.Select(x =>(string)x.GetValueByName(propertyName)).Distinct().OrderBy(x=> x).ToList();
    }
公共静态列表GetListOfProperty(IEnumerable listOfPersons,string propertyName)
{
返回listOfPersons.Select(x=>(string)x.GetValueByName(propertyName)).Distinct().OrderBy(x=>x.ToList();
}

如果要选择所有值:

object[] foos = objects.Select(o => o.GetType().GetProperty("PropertyName").GetValue(o)).ToArray();

除了显示调用GetProperty()的代码?DV以及在没有阅读MSDN文档的情况下到这里寻求帮助的代码之外,您还可以用文字说明您的问题吗。您的答案在文档中。@Crowcoder这只是另一个想要选择属性的人
var ids = listOfPersons.Query(p => p.Id);
var firstNames = listOfPersons.Query(p => p.FirstName);
var lastNames = listOfPersons.Query(p => p.LastName);
var cityNames = listOfPersons.Query(p => p.City);
var countryNames = listOfPersons.Query(p => p.CountryName);
public static List<string> Query(this IEnumerable<Person> instance, string property)
{
    switch (property)
    {
        case "ids": return instance.Query(p => p.Id.ToString());
        case "firstName": return instance.Query(p => p.FirstName);
        case "lastName": return instance.Query(p => p.LastName);
        case "countryName": return instance.Query(p => p.CountryName);
        case "cityName": return instance.Query(p => p.City);
        default: throw new Exception($"{property} is not supported");
    }
}
var cityNames = listOfPersons.Query("cityName");
public static class ObjectReflectionExtensions
{
    public static  object GetValueByName<T>(this T thisObject,  string propertyName)
    {
        PropertyInfo prop = typeof(T).GetProperty(propertyName);
        return prop.GetValue(thisObject);

    }
}
public static List<string> GetListOfProperty(IEnumerable<Person> listOfPersons, string propertyName)
    {
        return listOfPersons.Select(x =>(string)x.GetValueByName(propertyName)).Distinct().OrderBy(x=> x).ToList();
    }
object[] foos = objects.Select(o => o.GetType().GetProperty("PropertyName").GetValue(o)).ToArray();