Bar*_*rry 13 delphi comparison object
在Delphi中寻找一种方法来为我做深度对象比较,最好是2010 RTTI,因为我的对象不会继承TComponent.我正在开发一个测试框架DUnit并且需要一些可靠的东西,这将指出究竟哪个字段导致问题(序列化比较使它有点模糊).
Bar*_*rry 13
我自己解决这个问题,作为TObject的类助手实现,所以如果人们想要它可以在任何地方使用.由于RTTI而D2010及以上,但您可以将其转换为使用原始RTTI内容.
下面的代码可能是错误的,因为我最初是为了DUnit并且在其中进行了大量检查而不是更改结果并且不支持TCollections或其他特殊情况的加载但是可以通过使用if-elseif-then来适应它在中间切换.
如果您有任何建议和补充,请不要犹豫评论,以便我可以添加它,以便其他人可以使用它.
玩得开心编码
巴里
unit TObjectHelpers;
interface
uses classes, rtti;
type
TObjectHelpers = class Helper for TObject
function DeepEquals (const aObject : TObject) : boolean;
end;
implementation
uses sysutils, typinfo;
{ TObjectHelpers }
function TObjectHelpers.DeepEquals(const aObject: TObject): boolean;
var
c : TRttiContext;
t : TRttiType;
p : TRttiProperty;
begin
result := true;
if self = aObject then
exit; // Equal as same pointer
if (self = nil) and (aObject = nil) then
exit; // equal as both non instanced
if (self = nil) and (aObject <> nil) then
begin
result := false;
exit; // one nil other non nil fail
end;
if (self <> nil) and (aObject = nil) then
begin
result := false;
exit; // one nil other non nil fail
end;
if self.ClassType <> aObject.ClassType then
begin
result := false;
exit;
end;
c := TRttiContext.Create;
try
t := c.GetType(aObject.ClassType);
for p in t.GetProperties do
begin
if ((p.GetValue(self).IsObject)) then
begin
if not TObject(p.GetValue(self).AsObject).DeepEquals(TObject(p.GetValue(aObject).AsObject)) then
begin
result := false;
exit;
end;
end
else if AnsiSameText(p.PropertyType.Name, 'DateTime') or AnsiSameText(p.PropertyType.Name, 'TDateTime') then
begin
if p.GetValue(self).AsExtended <> p.GetValue(aObject).AsExtended then
begin
result := false;
exit;
end;
end
else if AnsiSameText(p.PropertyType.Name, 'Boolean') then
begin
if p.GetValue(self).AsBoolean <> p.GetValue(aObject).AsBoolean then
begin
result := false;
exit;
end;
end
else if AnsiSameText(p.PropertyType.Name, 'Currency') then
begin
if p.GetValue(self).AsExtended <> p.GetValue(aObject).AsExtended then
begin
result := false;
exit;
end;
end
else if p.PropertyType.TypeKind = tkInteger then
begin
if p.GetValue(self).AsInteger <> p.GetValue(aObject).AsInteger then
begin
result := false;
exit;
end;
end
else if p.PropertyType.TypeKind = tkInt64 then
begin
if p.GetValue(self).AsInt64 <> p.GetValue(aObject).AsInt64 then
begin
result := false;
exit;
end;
end
else if p.PropertyType.TypeKind = tkEnumeration then
begin
if p.GetValue(self).AsOrdinal <> p.GetValue(aObject).AsOrdinal then
begin
result := false;
exit;
end;
end
else
begin
if p.GetValue(self).AsVariant <> p.GetValue(aObject).AsVariant then
begin
result := false;
exit;
end;
end;
end;
finally
c.Free;
end;
end;
end.
Run Code Online (Sandbox Code Playgroud)
War*_* P 5
考虑使用OmniXML持久性。
对于XML差异,我使用OmniXML编写了一个实用程序,该实用程序将执行XML差异,并且那里有许多XML比较工具。
正是出于这个目的,我使用OmniXML来做一个XML差异工具,它对我来说非常有用。不幸的是,该工具包含许多特定于域的内容,并且是封闭源代码的,属于以前的雇主,因此我无法发布代码。
我的比较工具有一个简单的算法: