Issac
Issac

Reputation: 963

Implementing a generic extension

I have this method that extends IList<> for special ordering I need to implement. It takes an IList of IDisplayOrderable and an integer forRandom, and returns an ordered list but randomizing the items that have the DisplayOrder equals to the forRandom parameter.

public static IList<IDisplayOrderable> ReorderList(this IList<IDisplayOrderable> lstMain, int forRandom)
{
    List<IDisplayOrderable> result = new List<IDisplayOrderable>();
    Random rnd = new Random();
    result.AddRange(lstMain.Where(x => x.DisplayOrder.GetValueOrDefault(int.MaxValue) < forRandom).OrderBy(x => x.DisplayOrder.GetValueOrDefault(int.MaxValue)));
    result.AddRange(lstMain.Where(x => x.DisplayOrder.GetValueOrDefault(int.MaxValue) == forRandom).Shuffle(rnd));
    result.AddRange(lstMain.Where(x => x.DisplayOrder.GetValueOrDefault(int.MaxValue) > forRandom).OrderBy(x => x.DisplayOrder.GetValueOrDefault(int.MaxValue)));
    return result;
}

The IDisplayOrderable is a simple interface that expose the DisplayOrder for ordering different types.

public interface IDisplayOrderable
{
    Nullable<int> DisplayOrder { get; set; }
}

I want to achieve the same functionality but for a generic list that I wish to explicit set the 'OrderBy' property, something like:MyList.ReorderList(x=>x.DisplayOrder, 1000) but also MyOtherList.ReorderList(x=>x.OtherDisplayOrder, 1000). I read some about reflection to do this but haven't managed to get something working. Any help or direction would be appreciated

Upvotes: 1

Views: 75

Answers (1)

Alireza
Alireza

Reputation: 10476

Change ReorderList method so that it accepts a delegate returning the value of your desired property:

public static IList<T> ReorderList(this IList<T> lstMain,Func<T,int?> getter, int forRandom)
{
    List<T> result = new List<T>();
    Random rnd = new Random();
    result.AddRange(lstMain.Where(x => getter(x).GetValueOrDefault(int.MaxValue) < forRandom).OrderBy(x => getter(x).GetValueOrDefault(int.MaxValue)));
    result.AddRange(lstMain.Where(x => x.getter(x).GetValueOrDefault(int.MaxValue) == forRandom).Shuffle(rnd));
    result.AddRange(lstMain.Where(x => getter(x).GetValueOrDefault(int.MaxValue) > forRandom).OrderBy(x => xgetter(x).GetValueOrDefault(int.MaxValue)));
    return result;
}

and call it like:

MyOtherList.ReorderList(x=>x.OtherDisplayOrder, 1000)

Upvotes: 2

Related Questions