C# 创建用于比较自身实例的类的最佳方法
我正在编写一个程序,从数据库中获取数据,并将其逐值与旧数据进行比较,然后需要能够:C# 创建用于比较自身实例的类的最佳方法,c#,.net,oop,compare,data-annotations,C#,.net,Oop,Compare,Data Annotations,我正在编写一个程序,从数据库中获取数据,并将其逐值与旧数据进行比较,然后需要能够: 输出旧数据 输出新数据 仅输出差异 因此,为了简单起见,假设我创建了以下类来存储这些值: class MyClass { // These fields will not be compared: public string Id { get; set; } public string Name { get; set; } public string NONCompField1 {
class MyClass
{
// These fields will not be compared:
public string Id { get; set; }
public string Name { get; set; }
public string NONCompField1 { get; set; }
public int NONCompField2 { get; set; }
// These fields WILL be compared:
public string CompField1 { get; set; }
public int CompField2 { get; set; }
public int CompField3 { get; set; }
public double CompField4 { get; set; }
}
而且,正如我的示例中的名称所示,我想比较新旧值,但仅基于CompFields
来找出差异
我知道我可以按如下方式硬编码解决方案:
public IEnumerable<Tuple<string, string, string>> GetDiffs(MyClass Other)
{
var RetVal = new List<Tuple<string, string, string>>();
if (CompField1 != Other.CompField1)
RetVal.Add(Tuple.Create("CompField1", CompField1, Other.CompField1));
if (CompField2 != Other.CompField2)
RetVal.Add(Tuple.Create("CompField2", CompField2.ToString(), Other.CompField2.ToString()));
if (CompField3 != Other.CompField3)
RetVal.Add(Tuple.Create("CompField3", CompField3.ToString(), Other.CompField3.ToString()));
if (CompField4 != Other.CompField4)
RetVal.Add(Tuple.Create("CompField4", CompField4.ToString(), Other.CompField4.ToString()));
return RetVal;
}
public IEnumerable getDiff(MyClass其他)
{
var RetVal=新列表();
如果(CompField1!=其他.CompField1)
RetVal.Add(Tuple.Create(“CompField1”,CompField1,Other.CompField1));
如果(CompField2!=其他.CompField2)
添加(Tuple.Create(“CompField2”,CompField2.ToString(),Other.CompField2.ToString());
如果(CompField3!=其他.CompField3)
添加(Tuple.Create(“CompField3”,CompField3.ToString(),Other.CompField3.ToString());
如果(CompField4!=其他.CompField4)
添加(Tuple.Create(“CompField4”,CompField4.ToString(),Other.CompField4.ToString());
返回返回;
}
这给了我一个元组(Field\u Name
,Current\u Value
,Old\u Value
),效果很好,但我正在寻找一种更好的、模式动态的方法来实现这一点,它将允许将来添加新的字段-无论它们是CompareFields
(需要更新getdiff
)或nonmpfields
(无需更新getdiff
)
我的第一个想法是使用DataAnnotations
,然后使用反射来查找具有特定属性的字段,并为GetDiffs
方法循环这些字段,但这似乎是一种欺骗/糟糕的方法
是否有更好/更成熟的方法来实现这一点,从而最大限度地减少更新额外代码的需要
谢谢!!!创建一个代理列表,将项目投影到要比较的每个不同属性,然后比较两个项目上每个投影的结果:
public IEnumerable<Tuple<string, string, string>> GetDiffs(MyClass Other)
{
var comparisons = new[]
{
Tuple.Create<string, Func<MyClass, object>>("CompField1", item => item.CompField1),
Tuple.Create<string, Func<MyClass, object>>("CompField2", item => item.CompField2),
Tuple.Create<string, Func<MyClass, object>>("CompField3", item => item.CompField3),
Tuple.Create<string, Func<MyClass, object>>("CompField4", item => item.CompField4),
};
return from comparison in comparisons
let myValue = comparison.Item2(this)
let otherValue = comparison.Item2(Other)
where !object.Equals(myValue, otherValue)
select Tuple.Create(comparison.Item1,
myValue.ToString(),
otherValue.ToString());
}
public IEnumerable getDiff(MyClass其他)
{
var比较=新[]
{
Tuple.Create(“CompField1”,item=>item.CompField1),
Tuple.Create(“CompField2”,item=>item.CompField2),
Tuple.Create(“CompField3”,item=>item.CompField3),
Tuple.Create(“CompField4”,item=>item.CompField4),
};
比较中的比较返回
让myValue=comparison.Item2(此)
让otherValue=comparison.Item2(其他)
其中!object.Equals(myValue,otherValue)
选择Tuple.Create(comparison.Item1,
myValue.ToString(),
otherValue.ToString());
}
仅供参考-对于其他希望与我在这里所做相同操作的人,我最终修改了我找到的代码
这允许我做的是传入一个用于比较的属性名列表(尽管示例的作用正好相反——它有一个可以忽略的名称列表,但这是一个简单的更改),否则修改非常简单
希望这有助于至少在相同的情况下指导其他人。如果你不介意使用第三方工具,那么请多谢,YuvalItzchakov。我尽量避免使用外部的库,但这绝对是一件好事。谢谢!Servy,非常感谢。但是看起来这里仍然有需要。每次我添加一个新的(可比较的)属性时更新getdiff
方法。有什么原因比使用某种形式的DataAnnotation/Reflection(这只意味着在创建时装饰属性)更好吗?:)-真的,只是想知道你这样做是否有原因?如果出于某种原因这更好(我仍然是一个不折不扣的人,如果可能的话,我有兴趣学习最佳实践)