Утиный набор текста в Delphi 2007 (продолжение)?

Это продолжение этого сообщения.

Я уточнил свое требование на основе принятого ответа, опубликованного здесь.

Мой файл *.dpr:

program DuckD11;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  uDuckTyping in 'uDuckTyping.pas',
  uBirds in 'uBirds.pas';

procedure DoSomething(AObject: TObject);
begin
  Duck(AObject).Quack;
end;

var
  Bird: TBird;
  Ganagana: TGanagana;
  Canard: TCanard;
begin
  Writeln('Duck typing :');
  Writeln;

  Bird := TBird.Create('Bird');
  try
    DoSomething(Bird);
  finally
    Bird.Free;
  end;

  Ganagana := TGanagana.Create;
  try
    DoSomething(Ganagana);
  finally
    Ganagana.Free;
  end;

  Canard := TCanard.Create;
  try
    DoSomething(Canard);
  finally
    Canard.Free;
  end;

  Readln;
end.

Список uBirds.pas:

unit uBirds;

interface

uses
  SysUtils;

type
  {$METHODINFO ON}
  TBird = class
  private
    FName: string;
  public
    constructor Create(AName: string);
    procedure Quack;
  end;

  TGanagana = class
  private
    const cName = 'Ganagana';
  public
    procedure Quack;
  end;

  TCanard = class
  private
    const cName = 'Canard';
  public
    procedure Quack;
  end;

  {$METHODINFO OFF}

implementation

{ TBird }

constructor TBird.Create(AName: string);
begin
  FName := AName;
end;

procedure TBird.Quack;
begin
  Writeln(Format('  %s->Quack',[Self.FName]));
end;

{ TGanagana }

procedure TGanagana.Quack;
begin
  Writeln(Format('  %s=>Quack',[Self.cName]));
end;

{ TCanard }

procedure TCanard.Quack;
begin
  Writeln(Format('  %s::Quack',[Self.cName]));
end;

end.

Моя попытка кодирования uDuckTyping.pas:

unit uDuckTyping;

interface

type
  IDuck = interface
    ['{41780389-7158-49F7-AAA5-A4ED5AE2699E}']
    procedure Quack;
  end;

function Duck(AObject: TObject): IDuck;

implementation

uses
  ObjAuto;

type
  TDuckObject = class(TInterfacedObject, IDuck)
  private
    FObj: TObject;

    // ???

  protected
      procedure Quack;
  public
    constructor Create(AObject: TObject);
  end;

function Duck(AObject: TObject): IDuck;
begin
  Result := TDuckObject.Create(AObject);
end;

{ TDuckObject }

constructor TDuckObject.Create(AObject: TObject);
begin
  FObj := AObject;

  // ???
end;

procedure TDuckObject.Quack;
begin
  // ???
end;

end.

Мой вопрос:

я хочу использовать

  • ObjAuto.GetMethodInfo, чтобы убедиться в существовании обернутого метода Quack.
  • ObjAuto.ObjectInvoke для вызова обернутого метода Quack.

Как я могу завершить код?


person menjaraz    schedule 09.03.2012    source источник
comment
Почему бы вам просто не вызвать его и не поймать исключение? Я смеюсь над тем, что вы просили динамическую типизацию, а теперь не хотите просто использовать ее и обрабатывать последствия единственным возможным способом (обработка исключений).   -  person Warren P    schedule 09.03.2012
comment
Я просто пытаюсь воспроизвести Duck typing, как Даниэле Тети в ОБЩЕЖИТИИ (Dorm.utils.TDuckTypedList), но с D2007. Он использовал TRttiMethod в сочетании с Invoke (нацеленный на Delphi 2010 и более поздние версии) в два этапа: 1) Извлечь метод Rtti и сохранить его где-нибудь и, в конечном итоге, вызвать исключение в случае отсутствия метода или несоответствия подписи 2) Использовать позже сохраненный Rtti для вызова метода метод с соответствующими параметрами.   -  person menjaraz    schedule 09.03.2012
comment
Я думаю, вы выполняете обработку на основе IDispatch в Delphi, что гомоморфно хранилищу TRttiMethod в Delphi 2010 и более поздних версиях.   -  person Warren P    schedule 10.03.2012


Ответы (1)


В итоге я заставляю его работать после многих испытаний:

Изменения в модуле uDucktyping.pas:


Поля, добавленные как закрытые в определение класса TDuckObject

FQuackPMethodInfo: PMethodeInfoHeader;
FParamIndexes: array of Integer;
FParams: array of Variant;

Инициализация FQuackPMethodInfo в реализации TDuckObject.Create

FQuackPMethodInfo := GetMethodInfo(AObject, ShortString('Quack'));

Для добавления сразу после оператора инициализации FObj.


Вызов "Quack" в реализации TDuckObject.Quack

if Assigned(FQuackPMethodInfo) then
  ObjectInvoke(FObj, FQuackPMethodInfo, FParamIndexes, FParams);
person menjaraz    schedule 10.03.2012
comment
Я думаю, что то, что вы пытаетесь сделать, похоже на TVirtualInterface, представленный в XE2. Хотя в этом простом случае метода без параметров это легко сделать, это может усложниться, если у вас есть несколько методов с аргументами. В то время как утиная типизация в основном является шаблоном адаптера, то, что вы сделали, больше похоже на конкретный адаптер (TObject to IDuck). - person Stefan Glienke; 12.03.2012
comment
@Stefan Glienke: Вы правы, мой образец очень сфокусирован и ограничен: мне нужно выяснить, как правильно обращаться к методам обработки с аргументами и, в конечном итоге, возвращать значение. Кстати, вы упомянули TVirtualInterface, и я знаю, что вы сделали резервную копию, если вы можете рассмотреть это опубликовать пожалуйста? - person menjaraz; 14.03.2012
comment
@Stefan Glienke: я тщательно изучил DSharp.Core.Plugins.pas и очень ценю это. Да! TVVirtualInterface очень эффективен. - person menjaraz; 30.03.2012