我试图创建一个泛型方法,我想用它来混合一个属性的对象列表。 (可选)您可以提供列表对象列表以将某些组合并在一起。这可以作为非泛型方法正常工作,当我手动编写属性等时
方法主管:
public static IEnumerable<T> MixObjectsByProperty<T>(
IEnumerable<T> objects,
string propertyName,
IEnumerable<IEnumerable<T>> groupsToMergeByProperty = null)
方法体的片段:
groups =
(from item in objects
let propertyInfo = item.GetType().GetProperty(propertyName)
where propertyInfo != null
group item by groupsToMergeByProperty
.FirstOrDefault(ids => ids.Contains(propertyInfo.GetValue(item, null)))
//.FirstOrDefault(ids => ids.Any(propertyInfo.GetValue(item, null)))
?.First()
?? propertyInfo.GetValue(item, null)
into itemGroup
select itemGroup.ToArray())
.ToList();
正如您所看到的,我在IEnumerable<T>
上使用contains方法时遇到问题propertyInfo.GetValue(item, null)
正在返回一个对象。我已经尝试了各种投射尝试并使用.Any()
代替了,但我碰到了一堵砖墙:(
任何帮助都会很棒,谢谢!
另外,如果您需要更多信息,请告诉我,但我想,我想知道的是如何使用.Contains()
<T>
来使用IEqualityComparer
。
将它们设置为相同的类型?自定义$('.my-input:checked').each(function() {
//do something
});
?
答案 0 :(得分:1)
我尝试了各种投射尝试
你试过这个吗?
.FirstOrDefault(ids => ids.Contains((T)propertyInfo.GetValue(item, null)))
由于ids
的类型为IGrouping<TKey, TElement>
,其中TElement
的类型为T
,因此将属性值强制转换为T
将允许比较。
答案 1 :(得分:1)
没有看到整个方法(因为你的类型签名清楚地表明它不是整个方法),这里是一个示例实现:
public class Ext
{
public static List<T[]> MixObjectsByProperty<T, TProp, U>(
IEnumerable<T> source,
Expression<Func<T, TProp>> property,
IEnumerable<IEnumerable<U>> groupsToMix = null)
where T : class
where U : TProp
{
var prop = (PropertyInfo)(property.Body as MemberExpression)?.Member;
if (prop == null) throw new ArgumentException("Couldn't determine property");
var accessor = property.Compile();
var groups =
from item in source
let value = (U)accessor(item)
group item by
groupsToMix.FirstOrDefault((ids => ids.Contains(value)))
into itemGroup
select itemGroup.ToArray();
return groups.ToList();
}
}
对于上帝的爱停止传递属性名称并使用反射,Linq的其余部分使用华丽的表达系统,你也应该这样做!
答案 2 :(得分:-1)
好的,所以我最终破解了它。我需要在我的通用方法标题/签名中添加更多细节。
public static IEnumerable<T> MixObjectsByProperty<T, U>(
IEnumerable<T> objects, string propertyName, IEnumerable<IEnumerable<U>> groupsToMergeByProperty = null)
where T : class
where U : class
{
...
注意,我添加了类约束,允许我使用可空操作符等。
身体变成了(在添加了一个属于正确类型的propertyValue变量之后!):
groups =
(from item in objects
let propertyInfo = item.GetType().GetProperty(propertyName)
where propertyInfo != null
let propertyValue = (U)propertyInfo.GetValue(item, null)
group item by
groupsToMergeByProperty
.FirstOrDefault(ids => ids.Contains(propertyValue))
?.First()
?? propertyValue
into itemGroup
select itemGroup.ToArray())
.ToList();