通用IEqualityComparer使用反射和属性来标记我想要比较的内容
本文关键字:我想要 比较 IEqualityComparer 反射 属性 通用 | 更新日期: 2023-09-27 18:33:22
交叉点应该产生 0 条记录,因为名字和姓氏不合时宜。 我哪里做错了....?我怀疑是在平等实施中。
谢谢你,所有的问题都解决了(特别感谢Lasse V. Karlsen在钱上用gethashcode):等于加上哈希码错误解决了问题。
测试代码
var test1 = new ClassA { employeeid = 1, firstName = "a", lastname = "a" };
var test2 = new ClassA { employeeid = 1, firstName = "a", lastname = "b" };
IList<ClassA> listA = new List<ClassA>();
listA.Add(test1);
IList<ClassA> listB = new List<ClassA>();
listB.Add(test2);
//Actual Code
var Reflection = new ReflectionHelper();
var ListClassA = Reflection.GetPropertyNames<ClassA>();
var results = listA.Intersect(listB, new Compare<ClassA>(ListClassA)).ToList();
我的比较器
public class KeyComparerAttribute : Attribute{}
public class Compare<T> : IEqualityComparer<T> where T : class
{
IList<string> keyProperties = new List<string>();
public Compare(IList<string> keyProperties)
{
this.keyProperties = keyProperties;
}
public bool Equals(T x, T y)
{
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
{
return false;
}
var reflection = new ReflectionHelper();
foreach (var propName in keyProperties)
{
string val1 = reflection.GetPropertyValue<T>(propName, x);
string val2 = reflection.GetPropertyValue<T>(propName, y);
if (!val1.Equals(val2))
{
return false;
}
}
//if never false then it must be true....
return true;
}
public int GetHashCode(T obj)
{
int hash = 17;
foreach (var propInfo in keyProperties)
{
var myValue = reflection.GetPropertyValue(propName:propInfo, src: obj);
hash = hash * 23 + myValue.GetHashCode();
}
return hash;
}
}
我的帮助程序类仅供参考
public class ReflectionHelper
{
public IList<string> GetPropertyNames<T>()
{
IList<string> propertyNames = new List<string>();
var propertyInfos = typeof(T).GetProperties(
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Default |
BindingFlags.Instance).ToList().
Where(prop => Attribute.IsDefined(prop, typeof(KeyComparerAttribute)));
// write property names
if (propertyInfos.ToList().Count > 0)
{
foreach (PropertyInfo propertyInfo in propertyInfos)
{
propertyNames.Add(propertyInfo.Name);
}
}
return propertyNames;
}
public string GetPropertyValue<T>(string propName, T src)
{
return src.GetType().GetProperty(propName).GetValue(src, null).ToString();
}
}
A类
public class ClassA
{
public int employeeid { get; set; }
[KeyComparer]
public string firstName { get; set; }
[KeyComparer]
public string lastname { get; set; }
}
根据我的高中数学:
SetA = {test1, test2}
SetB = {test1, test2}
SetA = SetB (conceptually speaking) => SetA (intersect) SetB = SetA
或者你期望看到什么?
如果将其更改为
SetA = {test1}
SetB = {test2}
你会得到{0}
(空集)。
无论如何,我不建议将其用于生产代码。至少,当您已经在反射助手中检查了类时,缓存属性信息。
如果您有很多比较,则此代码将运行(相对)非常慢(正如您在实现此代码的推理中所暗示的那样)。虽然我非常喜欢避免编写样板代码,但有时由于性能/可维护性原因,编写它是值得的。