我想基于某些属性区分对象列表。这些属性是通过反射和一些条件得到的。我搜索了很多但是找不到能够在这个lambda表达式中循环的任何代码片段或解决方案。
List<PropertyInfo> propList = ...
var distinctList = FullList
.GroupBy(uniqueObj =>
{
//do a loop to iterate all elements in propList
})
.Select(x => x.First());
答案 0 :(得分:1)
您可以使用此方法使用属性名称创建表达式:
public static Expression<Func<T, object>> GetPropertySelector<T>(string propertyName)
{
var arg = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(arg, propertyName);
//return the property as object
var conv = Expression.Convert(property, typeof(object));
var exp = Expression.Lambda<Func<T, object>>(conv, new ParameterExpression[] { arg });
return exp;
}
并像这样使用:
var exp = GetPropertySelector<Person>("PropertyName");
现在你可以轻松搞清楚了:
List<Person> distinctPeople = allPeople
.GroupBy(exp.Compile())
.Select(g => g.First())
.ToList();
答案 1 :(得分:1)
好的,我花了一段时间才想到这一点。
基本上,您可以使用Linq GroupBy
运算符,但是您需要使用接受自定义IEQualityComparer
的重载,因为您要根据所有对象的子集验证对象的相等性属性。
属性子集存储在您在代码中的其他位置创建的List<PropertyInfo>
中,或者您从服务或其他任何位置创建的内容。
因此,实施IEqualityComparer
,然后将其与GroupBy
:
//Dummy class representing your data.
//
//Notice that I made the IEqualityComparer as a child class only
//for the sake of demonstration
public class DataObject
{
public string Name { get; set; }
public int Age { get; set; }
public int Grade { get; set; }
public static List<PropertyInfo> GetProps()
{
//Only return a subset of the DataObject class properties, simulating your List<PropertyInfo>
return typeof(DataObject).GetProperties().Where(p => p.Name == "Name" || p.Name == "Grade").ToList();
}
public class DataObjectComparer : IEqualityComparer<DataObject>
{
public bool Equals(DataObject x, DataObject y)
{
if (x == null || y == null)
return false;
foreach (PropertyInfo pi in DataObject.GetProps())
{
if (!pi.GetValue(x).Equals(pi.GetValue(y)))
return false;
}
return true;
}
public int GetHashCode(DataObject obj)
{
int hash = 17;
foreach (PropertyInfo pi in DataObject.GetProps())
{
hash = hash * 31 + pi.GetValue(obj).GetHashCode();
}
return hash;
}
}
}
//Then use that in your code:
//
List<DataObject> lst = new List<DataObject>();
lst.Add(new DataObject { Name = "Luc", Age = 49, Grade = 100 });
lst.Add(new DataObject { Name = "Luc", Age = 23, Grade = 100 });
lst.Add(new DataObject { Name = "Dan", Age = 49, Grade = 100 });
lst.Add(new DataObject { Name = "Dan", Age = 23, Grade = 100 });
lst.Add(new DataObject { Name = "Luc", Age = 20, Grade = 80 });
List<DataObject> dist = lst.GroupBy(p => p, new DataObject.DataObjectComparer()).Select(g => g.First()).ToList();
//The resulting list now contains distinct objects based on the `Name` and `Grade` properties only.
我希望这有助于您更接近解决方案。
干杯