C# 如何检查对象内容相等而不是对象引用相等
我有一个实体框架实体,看起来像这样:C# 如何检查对象内容相等而不是对象引用相等,c#,reflection,properties,C#,Reflection,Properties,我有一个实体框架实体,看起来像这样: class ListItemEtlObject { public int ID { get; set; } public string ProjectName { get; set; } public string ProjectType { get; set; } public string ProjectCode { get; set; } public string ProjectDescription { ge
class ListItemEtlObject
{
public int ID { get; set; }
public string ProjectName { get; set; }
public string ProjectType { get; set; }
public string ProjectCode { get; set; }
public string ProjectDescription { get; set; }
public string JobNo { get; set; }
public string JobDescription { get; set; }
public bool Include { get; set; }
}
我正在将两个不同数据源中的项拉入IEnumerable列表。如果不使用一堆if语句来检查属性值之间是否存在差异,然后在不匹配时设置属性值,那么如何进行项目比较?这样做的目的是使列表保持同步。列表A也设置了ID值,列表B没有。我只是觉得有一个更好的方法比一堆
if(objectA.ProjectName != objectB.ProjectName)
{
objectA.ProjectName = objectB.ProjectName;
}
如果您可以控制源对象,那么支持基于值的相等的最佳声明方式是实现
IEquatable
。不幸的是,这确实需要您枚举所有这些检查,但它在实际的对象定义位置执行一次,不需要在整个代码库中重复
class ListItemEtlObject : IEquatable<ListITemEtlObject>
{
...
public void Equals(ListITemEtlObject other) {
if (other == null) {
return false;
}
return
ID == other.ID &&
ProjectName == other.ProjectName &&
ProjectType == other.ProjectType &&
... ;
}
}
如果您可以控制源对象,那么支持基于值的相等的最佳声明方式是实现
IEquatable
。不幸的是,这确实需要您枚举所有这些检查,但它在实际的对象定义位置执行一次,不需要在整个代码库中重复
class ListItemEtlObject : IEquatable<ListITemEtlObject>
{
...
public void Equals(ListITemEtlObject other) {
if (other == null) {
return false;
}
return
ID == other.ID &&
ProjectName == other.ProjectName &&
ProjectType == other.ProjectType &&
... ;
}
}
最简单的方法是在类上提供一个计算特定散列的方法,很像
GetHashCode
,如果两个实例计算相同的散列,则可以说它们是等价的 最简单的方法是在类上提供一个计算特定哈希的方法,很像GetHashCode
,如果两个实例计算相同的哈希,则可以说它们是等价的 您可以使用reflection=)对其进行简化
您可以使用reflection=)简化它
可以使用反射创建比较函数。检查数据类型并为此编写一些比较代码。这可能已经足够好了。您可以使用反射创建一个比较函数。检查数据类型并为此编写一些比较代码。这可能已经足够好了。
public virtual void SetDifferences(MyBaseClass compareTo)
{
var differences = this.GetDifferentProperties(compareTo);
differences.ToList().ForEach(x =>
{
x.SetValue(this, x.GetValue(compareTo, null), null);
});
}
public virtual IEnumerable<PropertyInfo> GetDifferentProperties(MyBaseClass compareTo)
{
var signatureProperties = this.GetType().GetProperties();
return (from property in signatureProperties
let valueOfThisObject = property.GetValue(this, null)
let valueToCompareTo = property.GetValue(compareTo, null)
where valueOfThisObject != null || valueToCompareTo != null
where (valueOfThisObject == null ^ valueToCompareTo == null) || (!valueOfThisObject.Equals(valueToCompareTo))
select property);
}
[TestMethod]
public void CheckDifferences()
{
var f = new OverridingGetHashCode();
var g = new OverridingGetHashCode();
f.GetDifferentProperties(g).Should().NotBeNull().And.BeEmpty();
f.Include = true;
f.GetDifferentProperties(g).Should().NotBeNull().And.HaveCount(1).And.Contain(f.GetType().GetProperty("Include"));
g.Include = true;
f.GetDifferentProperties(g).Should().NotBeNull().And.BeEmpty();
g.JobDescription = "my job";
f.GetDifferentProperties(g).Should().NotBeNull().And.HaveCount(1).And.Contain(f.GetType().GetProperty("JobDescription"));
}
[TestMethod]
public void SetDifferences()
{
var f = new OverridingGetHashCode();
var g = new OverridingGetHashCode();
g.Include = true;
f.SetDifferences(g);
f.GetDifferentProperties(g).Should().NotBeNull().And.BeEmpty();
f.Include = true;
g.Include = false;
f.SetDifferences(g);
f.GetDifferentProperties(g).Should().NotBeNull().And.BeEmpty();
f.Include.Should().BeFalse();
}