C# 比较类型对象的类属性
我试图记录对象的每个属性在更新后的历史记录,只有当它发生更改时。我没有对每个属性执行if语句,而是决定循环遍历每个属性,在这些属性中我定义了一个自定义属性,以筛选出我不想记录的属性,然后比较新旧值以查看它们是否已更改 然而,检查每个obj实例的相等性似乎很大,而且非常具体,因为我还有枚举类型要比较。有没有更好的方法来实现这一点或重构我的代码 代码示例 MyClassC# 比较类型对象的类属性,c#,C#,我试图记录对象的每个属性在更新后的历史记录,只有当它发生更改时。我没有对每个属性执行if语句,而是决定循环遍历每个属性,在这些属性中我定义了一个自定义属性,以筛选出我不想记录的属性,然后比较新旧值以查看它们是否已更改 然而,检查每个obj实例的相等性似乎很大,而且非常具体,因为我还有枚举类型要比较。有没有更好的方法来实现这一点或重构我的代码 代码示例 MyClass public class MyClassDto { [Comparible] public MyC
public class MyClassDto
{
[Comparible]
public MyCustomType CustomType{ get; set; }
[Comparible]
public DateTime? SomeDate { get; set; }
[Comparible]
public decimal? SomeDecimalValue { get; set; }
[Comparible]
public int? SomeIntValue { get; set; }
// Other Non Custom Attribute Type Properties
}
添加历史辅助功能
public void AddHistory(MyClassDto prevMyObject, MyClassDto newMyObject)
{
if (prevMyObject== null || newMyObject == null) return;
foreach (var property in prevMyObject.GetType().GetProperties().Where(prop => Attribute.IsDefined(prop, typeof (ComparibleAttribute))))
{
var fieldName = property.Name;
object prevValue = property.GetValue(prevMyObject, null);
object newValue = newMyObject.GetType().GetProperty(property.Name).GetValue(newMyObject, null);
if (!IsEqual(prevValue, newValue))
{
//Log the field, prevValue, newValue
}
}
}
private static bool IsEqual(object obj1, object obj2)
{
if (obj1 == null && obj2 == null || obj1 == obj2) return true;
if (obj1 == null || obj2 == null) return false;
var objType = obj1.GetType();
if (objType == typeof (string))
{
return string.Equals(obj1.ToString(), obj2.ToString());
}
if (objType == typeof (int?))
{
return (Convert.ToInt32(obj1) == Convert.ToInt32(obj2));
}
if (objType == typeof (decimal?) || objType == typeof (decimal))
{
return (decimal.Round(Convert.ToDecimal(obj1), 2) == decimal.Round(Convert.ToDecimal(obj2), 2));
}
if (objType == typeof (DateTime?) || objType == typeof (DateTime))
{
return (Convert.ToDateTime(obj1) == Convert.ToDateTime(obj2));
}
if (objType == typeof (ContractTrackerType))
{
return (((MyCustomType) obj1).Name() == ((MyCustomType ) obj2).Name());
}
return false;
}
对象比较功能
public void AddHistory(MyClassDto prevMyObject, MyClassDto newMyObject)
{
if (prevMyObject== null || newMyObject == null) return;
foreach (var property in prevMyObject.GetType().GetProperties().Where(prop => Attribute.IsDefined(prop, typeof (ComparibleAttribute))))
{
var fieldName = property.Name;
object prevValue = property.GetValue(prevMyObject, null);
object newValue = newMyObject.GetType().GetProperty(property.Name).GetValue(newMyObject, null);
if (!IsEqual(prevValue, newValue))
{
//Log the field, prevValue, newValue
}
}
}
private static bool IsEqual(object obj1, object obj2)
{
if (obj1 == null && obj2 == null || obj1 == obj2) return true;
if (obj1 == null || obj2 == null) return false;
var objType = obj1.GetType();
if (objType == typeof (string))
{
return string.Equals(obj1.ToString(), obj2.ToString());
}
if (objType == typeof (int?))
{
return (Convert.ToInt32(obj1) == Convert.ToInt32(obj2));
}
if (objType == typeof (decimal?) || objType == typeof (decimal))
{
return (decimal.Round(Convert.ToDecimal(obj1), 2) == decimal.Round(Convert.ToDecimal(obj2), 2));
}
if (objType == typeof (DateTime?) || objType == typeof (DateTime))
{
return (Convert.ToDateTime(obj1) == Convert.ToDateTime(obj2));
}
if (objType == typeof (ContractTrackerType))
{
return (((MyCustomType) obj1).Name() == ((MyCustomType ) obj2).Name());
}
return false;
}
基本类型实际上不需要单独的案例。对于自定义类型,应该让它们重写,以便将相等性测试逻辑封装在类中 这样,您的
IsEqual
函数应该只是调用:
从object.Equals
的注释中:
static Equals(Object,Object)方法指示两个对象objA和objB是否相等。它还允许您测试值为null的对象是否相等。它比较了objA和objB的相等性,如下所示:
它确定两个对象是否表示相同的对象引用。如果是,则该方法返回true。此测试相当于调用ReferenceEquals方法。此外,如果objA和objB都为null,则该方法返回true
它确定objA或objB是否为空。如果是,则返回false
如果这两个对象不代表相同的对象引用,并且都不为null,那么它将调用objA.Equals(objB)并返回结果。这意味着如果objA重写Object.Equals(Object)方法,则调用此重写
非常感谢。完全忽略了object.equals方法。我假设当涉及枚举时,它仍然会正确地调用objA.Equals(objB)来计算它的实际值,或者枚举是否需要覆盖对象。Equals?@Kaustix是的,枚举类型有自己的Equals覆盖:谢谢!请吃一块饼干!