我希望通过反映KeyAttribute属性值来获取两个列表的交集:
这给了我主键属性(对于复合):
IEnumerable<PropertyInfo> keys = typeof(T).GetProperties().Where(prop => prop.IsDefined(typeof(KeyAttribute)));
现在,我如何找到两个列表的交集?
private static ICollection<T> Except<T>(this ICollection<T> source, ICollection<T> toIgnore)
{
IEnumerable<PropertyInfo> keys = typeof(T).GetProperties().Where(prop => prop.IsDefined(typeof(KeyAttribute)));
return source.Where(x => ???);
}
我想要的最终用例是:var result = firstList.Except(second);
它必须返回第一个列表中与第二个列表不匹配键属性值的项目。
编辑:
我可以做类似的事情,但它只适用于一个属性
public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKey)
{
return from item in items
join otherItem in other on getKey(item) equals getKey(otherItem) into tempItems
from temp in tempItems.DefaultIfEmpty()
where ReferenceEquals(null, temp) || temp.Equals(default(T))
select item;
}
private static int GetPrimaryKey<T>(T item)
{
foreach (PropertyInfo property in item.GetType().GetProperties())
{
KeyAttribute attr = property.GetCustomAttribute<KeyAttribute>();
if (attr != null)
{
return int.Parse(property.GetValue(item).ToString());
}
}
return -1;
}
答案 0 :(得分:1)
根据您的实际用例,您可以考虑构建表达式树来执行一些缓存。无论如何,这是一个直接的反射解决方案(https://dotnetfiddle.net/zfK1SU):
public class Program
{
public static void Main(string[] args)
{
var l1 = new List<ClassB>()
{
new ClassB() { KeyOne = 3, KeyTwo = 0 },
new ClassB() { KeyOne = 5, KeyTwo = 0 },
new ClassB() { KeyOne = 3, KeyTwo = 1 },
new ClassB() { KeyOne = 5, KeyTwo = 1 }
};
var l2 = new List<ClassB>()
{
new ClassB() { KeyOne = 5, KeyTwo = 0 }
};
var x = Except(l1, l2).ToList();
x.Dump();
}
public static IEnumerable<T> Except<T>(IEnumerable<T> items, IEnumerable<T> other)
{
var keyProps = typeof(T).GetProperties().Where(prop => prop.IsDefined(typeof(KeyAttribute))).ToList();
return items.Where(x => !other.Any(o => keyProps.All(prop => prop.GetValue(x).Equals(prop.GetValue(o)))));
}
}
public class ClassB
{
[Key]
public int KeyOne { get; set; }
[Key]
public int KeyTwo { get; set; }
public string NoKey { get; set; }
}