FoxSix
FoxSix

Reputation: 35

How to call a Generic method with dynamic properties in C#

I have the a few methods that have similar signature and was trying to convert them into one generic one without the use of interfaces.

 public List<MultiSelectDropdown> ConvertListOfJobStatusToDropdownListClickable(List<JobStatus> js) {
        var list = new List<MultiSelectDropdown>();
        if (js != null && js.Count >= 1) {
            list = js.Select(item => new MultiSelectDropdown { Name = item.StatusValue, Value = item.id.ToString() }).ToList();
        }
        return list;
    }


    public List<MultiSelectDropdown> ConvertListOfCUsersToDropdownListClickable(List<cUser> users) {
        var list = new List<MultiSelectDropdown>();
        if (users != null && users.Count >= 1) {
            list = users.Select(item => new MultiSelectDropdown { Name = item.User_Name, Value = item.Id.ToString() }).ToList();
        }
        return list;
    }

This is what I would like to do; pass in a list with two properties.

List<MultiSelectDropdown> ddlForClientUsers = ConvertToMultiSelectDropdownList(listOfClientsForUser, n => n.Client_Id, v => v.Client);

List<MultiSelectDropdown> ddlForJobStatus = ConvertToMultiSelectDropdownList(listOfJobStatus, n => n.Id, v => v.JobName);

This is the method I have tried but not sure how to get item.propName and item.propValue to work.

I get "Cannot resolve" propName and propValue in the method below

Is this possible?

 public List<MultiSelectDropdown> ConvertToMultiSelectDropdownList<T, TPropertyName, TPropertyValue>(List<T> listOfT, Func<T, TPropertyName> propName, Func<T, TPropertyValue> propValue) {
var list = new List<MultiSelectDropdown>();
        if (listOfT != null && listOfT.Count >= 1) {
            list = listOfT.Select(item => new MultiSelectDropdown { Name = item.propName, Value = item.propValue }).ToList();
        }
        return list;
    }

public class MultiSelectDropdown {
    public string Name { get; set; }
    public string Value { get; set; }
    public bool IsChecked { get; set; }
}

Upvotes: 3

Views: 189

Answers (2)

David Arno
David Arno

Reputation: 43254

You are really close, with just a slight mistake. The line (reformatted to prevent scrolling):

list = listOfT.Select(item => new MultiSelectDropdown 
                                  { 
                                      Name = item.propName, 
                                      Value = item.propValue 
                                  }).ToList();

needs to be:

list = listOfT.Select(item => new MultiSelectDropdown 
                                  { 
                                      Name = propName(item), 
                                      Value = propValue(item)
                                  }).ToList();

Upvotes: 1

Glorfindel
Glorfindel

Reputation: 22631

Because the properties of your MultiSelectDropdown are strings, your functions should return those as well. And to invoke the functions, you have to write them like propName(item) instead of item.propName - that is the property syntax, and you indicated you didn't want to use interfaces.

public List<MultiSelectDropdown> ConvertToMultiSelectDropdownList<T>(List<T> listOfT, Func<T, string> propName, Func<T, string> propValue) {
    var list = new List<MultiSelectDropdown>();
    if (listOfT != null && listOfT.Count >= 1) {
        list = listOfT.Select(item => new MultiSelectDropdown { Name = propName(item), Value = propValue(item) }).ToList();
    }
    return list;
}

Upvotes: 3

Related Questions