0

Let's say I have a simple list of objects like this:

public class DataField
{
    public int DataFieldId {get; set;}
    public int KeyId {get; set;}
    public string FieldName {get; set;}
    public string Data {get; set;}
}

Now I would like to get a list of the values in a Property using the string value of the Property name, like this:

public List<string> getFieldData(List<DataField> dataToSearch, string propertyName)
{
    // This is the area I'd like to figure out.
    return dataToSearch.Select(ds => ds.propertyName).Distinct.ToList();
}

public void MyMethod()
{
    var data = new List<DataField>{
        new DataField{DataFieldId = 1, KeyId = 1,
            FieldName = "UserName", Data = "jSmith"},
        new DataField{DataFieldId = 2, KeyId = 1,
            FieldName = "Email", Data = "jSmith@nowhere.com"},
        new DataField{DataFieldId = 3, KeyId = 1,
            FieldName = "PreferredContact", Data = "Phone"},
        new DataField{DataFieldId = 4, KeyId = 2,
            FieldName = "UserName", Data = "jDoe"},
        new DataField{DataFieldId = 5,KeyId = 2,
            FieldName = "Email", Data = "janeDoe@emailServer.net"},
        new DataField{DataFieldId = 6, KeyId = 2,
            FieldName = "PreferredContact", Data = "Email"}
    };

    // Notice I want to search using a string
    var fieldNames = getFieldData(data, "FieldName");
}

I would want fieldNames to be a List<string> containing:
"UserName"
"Email"
"PreferredContact"

I would like to use a string to specify the column to return.

M Kenyon II
  • 4,136
  • 4
  • 46
  • 94

1 Answers1

4

You can use reflection. You're using "field" but the class actually contains properties, so use reflection's GetProperty() method. If you use fields instead, use GetField()

public static List<string> getFieldData(List<DataField> dataToSearch, string fieldName)
{
    // You can use reflection to get information from types at runtime.
    // The property_info variable will hold various data about the field
    // name you pass in (type, name, etc)
    var property_info = typeof(DataField).GetProperty(fieldName);

    // We can then call property_info's GetValue() on an instantiated 
    // object of our class, and it will return the value of that property on that object
    return dataToSearch.Select(ds => Convert.ToString(property_info.GetValue(ds))).Distinct().ToList();
}

PropertyInfo class: https://msdn.microsoft.com/en-us/library/system.reflection.propertyinfo(v=vs.110).aspx

Type class: https://msdn.microsoft.com/en-us/library/system.type(v=vs.110).aspx

Marco S.
  • 3
  • 1
Marco Fatica
  • 937
  • 7
  • 12
  • 3
    +1. Also, just in case OP isn't familiar with the field vs property distinction in C# which you mention: http://stackoverflow.com/a/295109/424129 – 15ee8f99-57ff-4f92-890c-b56153 Jan 11 '16 at 17:07
  • My code looks like this: `keys = thisSection.ReportItems.Select(ds => Convert.ToString(propertyInfo.GetValue(ds))).Distinct().ToList();` I get this: Error 3 'System.Collections.ICollection' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.Collections.ICollection' could be found (are you missing a using directive or an assembly reference?) – M Kenyon II Jan 11 '16 at 17:30
  • @MKenyonII what is the type of `thisSection.ReportItems`? – Marco Fatica Jan 11 '16 at 18:16
  • thisSection.ReportItems is of type `ICollection`. – M Kenyon II Jan 12 '16 at 18:52
  • what type of items are stored in the `ICollection`? you will need to cast it to `ICollection` for whichever class is stored in the collection. for example, if the `ICollection` held `DataField` objects, change the call `thisSection.ReportItems.Select` to `thisSection.ReportItems.Cast().Select` – Marco Fatica Jan 13 '16 at 15:36