Description
Reflection is a great tool when it comes to handling the information at runtime. I found this solution below to be suitable in one of my applications because I wanted something that I could easily adapt.
The implementation of the method below looks for both public and private fields and properties.
public static partial class Extensions
{
public static IEnumerable DistinctBy<T, Tkey>(this IEnumerable @this, Expression<Func<T, object>> expression)
{
string binding = ReflectObj.ObjGetPropertyPath(expression);
return DistinctBy<T, Tkey>(@this, binding);
}
public static IEnumerable DistinctBy<T, Tkey>(this IEnumerable @this, string binding)
{
string[] _params = binding.Split('.');
IList list = new List();
IList ReturnList = new List();
//
foreach (var item in @this)
{
//get key
object Key = item;
foreach (var _param in _params)
{
Type t = Key.GetType();
PropertyInfo pi = t.GetProperty(_param, BindingFlags.Public | BindingFlags.Instance);
Key = pi.GetValue(Key);
}
if (list.Where(x => x.Equals(Key)).Count() == 0)
{
list.Add((Tkey)Key);
ReturnList.Add(item);
}
list.Add((Tkey)Key);
}
return ReturnList;
}
}
Usage
Let’s create a product class that has a Price. We aim to easily create a list with unique “parameters” that will be defined in a string.
class Price
{
public double Value { get; set; }
}
class Product
{
public string Name { get; set; }
public Price Price { get; set; }
private int NoPrice;
}
class Program
{
static void Main(string[] args)
{
List Products = new List
{
new Product{ Name = "Product1", Price = new Price{ Value = 100} },
new Product{ Name = "Product2", Price = new Price{ Value = 100} },
new Product{ Name = "Product3", Price = new Price{ Value = 200} }
};
// will result 1 item, NoPrice default for all is 0
var DistinctProducts1 = Products.DistinctBy<Product, int>("NoPrice");
// will result 3 items, no such key is found
var DistinctProducts2 = Products.DistinctBy<Product, int>("NoPrice.Test");
// will result 2 items - Value is 100 for 2 of them
var DistinctProducts3 = Products.DistinctBy<Product, int>("Price.Value");
}
}
}







