Подтвердить что ты не робот

Сравнение Deep Object Delphi

Ищем библиотеку delphi или фрагмент кода, который будет выполнять глубокое сравнение объектов для меня, желательно RTTI 2010, поскольку мои объекты не наследуются от TComponent. Кто-нибудь знает, где я могу его найти, я разрабатываю тестовую структуру в DUnit и нуждаюсь в чем-то солидном, который указывает, в каком именно поле возникают проблемы (сравнение сериализации немного смутно).

Приветствия,

Barry

4b9b3361

Ответ 1

Сорт решения этого сам, реализованный как помощник класса для 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.

Ответ 2

Рассмотрите возможность использования сохранения OmniXML.

Для разнесения XML я написал утилиту с использованием OmniXML, которая будет выполнять XML-diff, и есть много инструментов сравнения XML.

Я использовал OmniXML для создания инструмента для разграничения XML для этой цели, и он отлично работал у меня. К сожалению, этот инструмент содержит много специфических для домена вещей и является закрытым исходным кодом и принадлежит бывшему работодателю, поэтому я не могу опубликовать код.

У моего инструмента сравнения был простой алгоритм:

  • Сопоставьте и постройте карту Object1- > Object2 node связей между соответствующими узлами XML.
  • Отсортируйте каждый node на первичный ключ (знание домена), делая порядок XML несущественным. Поскольку вы не только сравниваете TComponents с именами, вам нужно найти способ установить каждый идентификатор объектов, если вы хотите сравнить его.
  • Элементы отчета в xml doc 1, которые не находятся в xml doc 2.
  • Элементы отчета в xml doc 2, которые не находятся в xml doc 1.
  • Элементы отчета в xml doc 1 с подразделами или атрибутами, отличными от xml doc2.
  • визуальный инструмент использовал два элемента управления Virtual Tree View и много работал как KDIFF3, но как treeview.