Duck typing en Delphi 2007 (continuación)?

Este es un seguimiento de esto post.

I refined my requirement based on the accepted answer posted aquí.

My *.dpr file:

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 listing:

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.

My attempt coding 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.

Mi pregunta es:

Quiero usar

  • ObjAuto.GetMethodInfo to ascertain the existence of the wrapped Quack method.
  • ObjAuto.ObjectInvoke to invoke the wrapped Quack method.

How can I complete the code ?

preguntado el 09 de marzo de 12 a las 15:03

Why don't you just call it, and catch the exception? I have to laugh that you asked for dynamic typing, and now you're reluctant to just use it, and handle the aftermath the only way you can (exception handling). -

I just try to reproduce Duck typing as Daniele Teti did in the DORM (Dorm.utils.TDuckTypedList) but with D2007. He used TRttiMethod in conjunction with Invoke (targeting Delphi 2010 onward) in two step : 1) Extract method Rtti and store it somewhere and eventually raise exception in case of absence of the method or signature mismatch 2) Use later the stored Rtti to Invoke the method with the appropriate parameters. -

You're doing IDispatch based handling in Delphi, I guess, which is homomorphic to TRttiMethod storage in Delphi 2010 onward. -

1 Respuestas

I end up getting it to work after many trial:

Modifications in the uDucktyping.pas unit:


Fields added as private in TDuckObject definición de clase

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

Initialization of FQuackPMethodInfo in TDuckObject.Create implementación

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

To append just after FObj initialization statement.


Invocación de "Quack" dentro de TDuckObject.Quack implementación

if Assigned(FQuackPMethodInfo) then
  ObjectInvoke(FObj, FQuackPMethodInfo, FParamIndexes, FParams);

respondido 10 mar '12, 12:03

I think what you are trying to do is similar to TVirtualInterface introduced in XE2. While it is easy for this simple case of a parameterless method this might get more complicated when you have multiple methods with arguments. While duck typing is basically the adapter pattern what you did is more like a specific adapter (TObject to IDuck). - Stefan Glienke

@Stefan Glienke: You are right, my sample is very focused and limited: I have to investigate how to properly address the handling methods with arguments and eventually return value. BTW, you mention TVirtualInterface and I know that you have done a backport of if, can you consider this post ¿por favor? - menjaraz

@Stefan Glienke: I have scrutinized DSharp.Core.Plugins.pas and appreciate it very much. Yes! TVirtualInterface is very capable. - menjaraz

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.