尋找一個delphi庫或代碼片段,將爲我做深度對象比較,最好是基於RTTI的,因爲我的對象不會從TComponent繼承。有誰知道我在哪裏可以找到一個,我正在開發一個測試框架在DUnit,並需要一些固體,它會指出究竟哪個字段導致問題(序列化比較離開它有點模糊)。深度對象比較Delphi
乾杯,
巴里
尋找一個delphi庫或代碼片段,將爲我做深度對象比較,最好是基於RTTI的,因爲我的對象不會從TComponent繼承。有誰知道我在哪裏可以找到一個,我正在開發一個測試框架在DUnit,並需要一些固體,它會指出究竟哪個字段導致問題(序列化比較離開它有點模糊)。深度對象比較Delphi
乾杯,
巴里
解決這個問題的種類,作爲TObject的類助手實現,所以如果人們需要它可以隨處使用。 D2010和以上,因爲RTTI,但你可能能夠將其轉換爲使用原始RTTI的東西。
下面的代碼可能是錯誤的,因爲我原來是用於DUnit的,它有很多檢查,而不是改變結果,不支持TCollections或其他特殊情況的負載,但可以通過使用if -elseif - 然後在中間切換。
如果您有任何建議和補充,請不要猶豫,以便我可以添加它,以便其他人可以使用它。
玩得開心編碼
巴里
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.
非顯着差異與顯着差異如何? (例子:你是否曾經想過忽略窗口句柄值等差異的情況?你可以添加一個排除屬性,以便深入比較可以跳過一些東西嗎? –
當有人對你的類型進行類型重定義時, –
或者如果人們已經在使用他們自己的(或別人的)類助手來處理TObject,那麼可以使用NOWHERE。對於大聲喊叫,人們什麼時候會停止使用類助手來處理那些單元級別的函數/程序足夠好,而且更合理!!它確實看起來好像人們非常渴望爲班級助手找到一個合法的用途,他們會在每個問題上拋出它們 - 其中99%是他們 – Deltics
考慮使用OmniXML persistence。
對於XML差異,我已經使用OmniXML編寫了一個實用程序,它將執行XML差異,並且有許多XML比較工具。
爲了達到這個目的,我使用了OmniXML來完成XML差異化工具,它對我來說非常好。不幸的是,該工具包含許多特定領域的東西,並且是封閉源代碼,屬於前僱主,因此我無法發佈代碼。
我比較工具有一個簡單的算法:
序列化到一個文本格式(XML,JSON),並做了TDIFF(http://angusj.com/delphi/)會很容易 – mjn
怎麼樣DFM格式:-)它就像一個JSON前身...從1995年開始。 –