Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

In the following, the method Obtain() works, but the GetAs() method would be neater for callers.

However, I can't figure out how to pass an interface as a generic parameter and obtain its GUID.

Declaration:

  TInterfaceRegistry = class
  private
    fRegistry: TDictionary<TGUID, IInterface>;
  public
    ...
    procedure Register(const IID: TGUID; IntfObj: IInterface; const Replace: Boolean = False);
    function  Obtain(const IID: TGUID; out IntfObj): Boolean;
    function  GetAs<I: IInterface>(): I;
  end;

Implementation:

function TInterfaceRegistry.Obtain(const IID: TGUID; out IntfObj): Boolean;
var
  Found: IInterface;
begin
  Result  := fRegistry.TryGetValue(IID, Found);
  if  Result  then
    if  not Supports(Found, IID, IntfObj) then
      raise EBatSoft.Create(SEBatSoftBug);
end;

function  TInterfaceRegistry.GetAs<I>(): I;
begin
  if  not Obtain(I, Result) then
    raise EBatSoft.Create(SEDoesNotImplement);
end;

Calling it looks like this...

  IntfReg.Register(IMyIntf, TMyImpl.Create);

Getting implementation:

var
  Intf: IMyIntf;
begin
  // Less type-safe (can pass anything into 2nd parameter)
  if IntfReg.Obtain(IMyIntf, Intf)  then
    ...
  // Fully type-safe, and simple
  Intf := IntfReg.GetAs<IMyIntf>();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
234 views
Welcome To Ask or Share your Answers For Others

1 Answer

You have to use typeinfo via GetTypeData(TypeInfo(I)).GUID.

Keep in mind though this might return an empty guid if you did not declare any for the given interface you are using while the non generic approach simply would not compile.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...