我正在编写一个程序,从数据库中获取数据并将其逐个值与旧数据进行比较,然后需要能够:
因此,为简单起见,假设我创建了以下类来存储值:
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;
}
这让我回到Tuple<string, string, string>
(Field_Name
,Current_Value
,Old_Value
)并且工作正常,但我正在寻找更好的,模式动态的方式,允许将来添加新字段 - 无论是CompareFields
(需要更新GetDiffs
)还是NONCompFields
(无需更新GetDiffs
)。
我的第一个想法是使用DataAnnotations
然后使用反射来查找具有特定属性的字段并循环使用GetDiffs
方法,但这似乎是一种欺骗/糟糕的做事方式
是否有更好/更成熟的方法来最大限度地减少更新额外代码的需要?
感谢!!!
答案 0 :(得分:1)
创建一个委托列表,将项目投射到您要比较的每个不同属性,然后比较这两个项目的每个投影的结果:
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());
}
答案 1 :(得分:1)
仅供参考 - 对于那些希望与我在此处所做的相同的人,我最终修改了我找到的代码here。
这允许我做的是传入一个属性名称列表以用于比较(虽然示例正好相反 - 它有一个要忽略的名称列表,但这很容易改变)并且修改很漂亮很简单。
希望这有助于至少引导其他人处于相同的情况。