根据运行时输入的 属性 将 List<Objects> 转换为 List<String>

Convert List<Objects> to List<String> based on property fed in at runtime

所以我有一个列表 Objects 让我们举个例子:

var animals = new List<Animal>() //add Animals`

我知道我可以将这些从 This Question 转换为 strings,例如:

List<Animal> animals = new List<Animal>();
List<string> strings = animals.Select(a => (string)a).ToList();

BUT 我想根据 属性 从 animals 的列表中获取 List<string> 作为 string 在运行时

例如:

private List<string> GetList(string property)
{
    return animals.Select(x => filterByReflection(property)).ToList();
}

所以我可以打电话给:

var names = GetList("Name");
var types = GetList("Type");
var ages = GetList("Age");

这可能吗?

是的,像这样:

private List<string> GetList(string property)
{
    return animals.Select(x => GetProperty(x, property)).ToList();
}

private static string GetProperty(Animal animal, string property)
{
    Type type = typeof(Animal);
    PropertyInfo propertyInfo = type.GetProperty(property);
    return (string)propertyInfo.GetValue(animal);
}

所以我发现我可以使用这些方法通过 Reflection

获得 PropertyInfo
private string GetValue(object item, string propString)
    {
        if (item != null)
        {
            if (!string.IsNullOrEmpty(propString))
            {
                try
                {
                    var property = GetProperty(item.GetType().GetTypeInfo(), AutoCompleteSourceMember);
                    if (property != null)
                    {
                        var value = property.GetValue(item);
                        if (value != null)
                        {
                            return value.ToString();
                        }

                    }
                    return string.Empty;

                }
                catch (Exception ex)
                {
                    return string.Empty;
                }
            }
            else
            {
                return item.ToString();
            }
        }
        return string.Empty;
    }

    private static PropertyInfo GetProperty(TypeInfo typeInfo, string propertyName)
    {
        var propertyInfo = typeInfo.GetDeclaredProperty(propertyName);
        if (propertyInfo == null && typeInfo.BaseType != null)
        {
            propertyInfo = GetProperty(typeInfo.BaseType.GetTypeInfo(), propertyName);
        }
        return propertyInfo;
    }

并像这样使用它:

private List<string> GetList(string property)
{
    return animals.Select(x => GetValue(x,property)).ToList();
}

因为你知道它们是 strings 你可以直接将 filterByReflection 的结果转换为 string:

private List<string> GetList(string property)
{
    return animals.Select(x => (string)filterByReflection(property)).ToList();
}

更一般地说,您可以使此方法通用:

private List<T> GetList<T>(string property)
{
    return animals.Select(x => (T)filterByReflection(property)).ToList();
}

当然,如果您传入的 属性 名称在第一种情况下不 return 为 string 或在第二种情况下为 T,您将得到一个InvalidCastException 在 运行 时间。

完整的工作示例:

class Program
{
    static List<Animal> animals = new List<Animal>();

    static void Main(string[] args)
    {
        animals.Add(new Animal() { Age = 3, Name = "Terry", Type = "Tiger" });
        animals.Add(new Animal() { Age = 1, Name = "Bob", Type = "Badger" });
        animals.Add(new Animal() { Age = 7, Name = "Alfie", Type = "Dog" });

        GetList("Age").ForEach(Console.WriteLine);

        Console.Read();
    }

    public static List<string> GetList(string property)
    {
        return animals.Select(o => o.GetType().GetProperty(property).GetValue(o).ToString()).ToList();
    }
}

class Animal
{
    public string Name { get; set; }
    public string Type { get; set; }
    public int Age { get; set; }
}

通用函数:

public static class Extensions
{
    public static IEnumerable<P> SelectProperty<T, P>(this IEnumerable<T> source, string propertyName)
    {
        var selector = (Func<T, P>)Delegate.CreateDelegate(typeof(Func<T, P>), typeof(T).GetProperty(propertyName).GetGetMethod());
        return source.Select(selector);
    }
}

和用法:

private List<string> GetList(string property)
{
    return animals.SelectProperty<Animal, string>(property).ToList();
}

这是最快的基于反射的方法,因为反射只进行一次,而不是像其他答案那样对每个项目进行反射。