0

So I have a list of Objects lets say for example:

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

I know I can convert these to strings from This Question like:

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

BUT I would like to get List<string> from the list of animals based on a property that I feed in as a string at runtime

For example:

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

so I can call:

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

Is this possible?

Community
  • 1
  • 1
JKennedy
  • 18,150
  • 17
  • 114
  • 198

5 Answers5

2

Yes, something like this:

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);
}
JoaoFSA
  • 267
  • 1
  • 7
2

Full working example:

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; }
}
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
0

So I found I can use these methods to get PropertyInfo via Reflection

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

and use it like:

private List<string> GetList(string property)
{
    return animals.Select(x => GetValue(x,property)).ToList();
}
JKennedy
  • 18,150
  • 17
  • 114
  • 198
0

Since you know that they are strings you can directly cast the result of filterByReflection to a string:

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

More generally you can make this method generic:

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

Of course if you pass in a property name that does not return a string in the first case or a T in the second you will get an InvalidCastException at run time.

shf301
  • 31,086
  • 2
  • 52
  • 86
0

A generic function:

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

and usage:

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

This is the fastest reflection based approach, because reflection is done just once instead of for each item as in other answers.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343