Casting a delphi interface to its implementation class without modifying the interface [duplicate]

浪尽此生 提交于 2019-12-01 07:23:58

问题


Possible Duplicate:
How to cast a Interface to a Object in Delphi

Using Delphi 5; I have an interface that I cannot change for legacy reasons. I am passing (pointers to) that interface all over the place. The implementing class has several new properties - is there a way to force a cast from the interface to the actual implementation?

http://www.malcolmgroves.com/blog/?p=500 says that this is (newly) implemented in Delphi 2010, which strongly suggest that it wasn't possible before. Is this indeed the case, or is there a way I'm not familiar with? RTTI, maybe?

(I checked, and if pScore is TOleScore then is indeed not allowed by the Delphi 5 compiler - here pScore is my pScore: IScore argument, and TOleScore is the implementing class.)


回答1:


  • The classic take on this is by Hallvard Vassbotn: Hack #7: Interface to Object
  • More recently Barry Kelly, a Delphi compiler engineer, also provided an implementation: An ugly alternative to interface to object casting

I think both approaches should work.


Incidentally, does anyone know if Hallvard is still active? I've not come across him in the past few years.




回答2:


H/t to my boss, the answer is: use the incredibly useful JEDI library, specifically the GetImplementorOfInterface method.




回答3:


i do what the "possible duplicate" question's accepted answer does:

Have the object implement the IObject interface:

IObject = interface(IUnknown)
    ['{39B4F98D-5CAC-42C5-AF8D-0237C8EFBE4C}']
    function GetSelf: TObject;
end;

So it would be:

var
   thingy: IThingy;
   o: TOriginalThingy;

begin
   o := (thingy as IObject).GetSelf as TOriginalThingy;

Update: To drive the point home, you can add a new interface to an existing object.

Existing object:

type
    TOriginalThingy = class(TInterfacedObject, IThingy)
    public
       //IThingy
       procedure DrinkCokeZero; safecall;
       procedure ExcreteCokeZero; cafecall;
    end;

Add IObject as one of the interfaces it exposes:

type
    TOriginalThingy = class(TInterfacedObject, IThingy, IObject)
    public
       //IThingy
       procedure DrinkCokeZero; safecall;
       procedure ExcreteCokeZero; cafecall;

       //IObject - provides a sneaky way to get the object implementing the interface
       function GetSelf: TObject;
    end;

    function TOriginalThingy.GetSelf: TObject;
    begin
       Result := Self;
    end;

Typical usage:

    procedure DiddleMyThingy(Thingy: IThingy);
    var
       o: TThingy;
    begin
       o := (Thingy as IObject).GetSelf as TThingy;

       o.Diddle;
    end;


来源:https://stackoverflow.com/questions/6414496/casting-a-delphi-interface-to-its-implementation-class-without-modifying-the-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!