0

I have a class file named ParentPropertyAttribute with a Type Property as below:

public Type PropertyType { get; set; }

In one of my class, I need to do some work based on the type passed. Right now, I am using if else condition as below:

 if (parentPropertyAttribute.PropertyType == typeof(string))
                {
                    return (parentList as IList<string>).Select(item => new SelectItem() { Value = item, Text = item }).OrderBy(selectItem => selectItem.Text);
                }
                else if (parentPropertyAttribute.PropertyType == typeof(XYZ))
                {
                    return (parentList as IList<XYZ>).Select(x=> new SelectItem() { Value = item, Text = item }).OrderBy(selectItem => selectItem.Text);
                }

The issue with the above is in future if there is any other type the if else case gets on increasing. Is there an optimized way to dynamically assign the type (string/XYZ in this case) to achieve this.

Any input is appreciated.

Regards.

Liam
  • 27,717
  • 28
  • 128
  • 190
Ms1
  • 45
  • 5
  • 3
    I would question why you have `public Type PropertyType { get; set; }` at all? We'll need more context here... – Liam Jul 27 '21 at 15:40
  • BTW there is no reflection here. – Liam Jul 27 '21 at 15:41
  • @Liam Reflection is actually somewhat relevant here, even though its not in his code. See https://stackoverflow.com/a/232621/8582381 (OP should also follow this link) – Kieran Moynihan Jul 27 '21 at 15:46
  • The second example can't say `Text = item` if `item` isn't a `string`, right? – StriplingWarrior Jul 27 '21 at 15:47
  • make `XYZ` and any new implement `IConvertableToSelectItem` then cast it to `IEnumerable` and use common method ... for standard types like `string`, `int` or others make your ifs – Selvin Jul 27 '21 at 15:53

2 Answers2

0

Since the only thing you're using with the IList<> interface is coming from the IEnumerable<> interface, there's a chance you could just do something like this:

return ((IEnumerable)parentList).Cast<object>()
    .Select(item => new SelectItem { Value = item, Text = item.ToString() })
    .OrderBy(selectItem => selectItem.Text)
    .ToList();

This depends on all the valid types in your lists having ToString() implementations that are appropriate for this purpose, though.

Note that the ((IEnumerable)parentList).Cast<object>() could be simplified to ((IEnumerable<object>)parentList) if you know none of the types are Value Types (which need boxing to convert into objects).

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Thanks.This worked like a charm with some modifications as per my class structure. – Ms1 Jul 27 '21 at 18:11
0

Of course you can. You just need more generics in your code. Please refer to this example:

class SmartListItem
{
    public string Name { get; set; }
}

class SmartList
{
    private System.Collections.IList list;

    public SmartList(System.Collections.IList list)
    {
        this.list = list;
    }

    public List<T> FilterPropertyType<T>(Func<T, bool> query)
    {
        return list.Cast<T>().Where(query).ToList();
    }
}

You can use this "SmartList" in different ways (without use ParentType because is not necessary):

var stringList = new SmartList(new[] { "Rob", "Liam" });
var matches = stringList.FilterPropertyType<string>(s => s.Contains("Rob"));

Or better with classes:

var classList = new SmartList(new []{
  new SmartListItem { Name = "Rob" },
  new SmartListItem { Name = "Liam" }
});
var matches = classList.FilterPropertyType<SmartListItem>(smi => smi.Name.Contains("Rob"));

Using that you can avoid switch case for PropertyType and do your queries directly on the list item.

Roberto Conte Rosito
  • 2,080
  • 12
  • 22