Search code examples
delphidelphi-xe7spring4d

Typed interfaces and Spring4D


I am trying to use typed interfaces and Spring4D, but have some issues with Resolving. Please review details below.

DB Objects:

unit u_DB;

type
  TDBObject = class
  public
    property ID: TGUID;
  end;

  TDBCRM = class(TDBObject)
  public
    property SOME_FIELD: TSomeType;
  end;

Declarations:

unit i_BaseDAL;

type
  {$M+}
  IBaseDAL<T: TDBObject, constructor> = interface
  ['{56D48844-BD7F-4FF8-A4AE-30DA1A82AD67}']
    procedure RefreshData();
    ....
  end;

unit u_BaseDAL;

type
  TBaseDAL<T: TDBObject, constructor> = class(TInterfacedObject, IBaseDAL<TDBObject>)
  public
    procedure RefreshData();
  ....
  end;

After that I was able to register the base IBaseDAL and IBaseDAL

GlobalContainer.RegisterType<IBaseDAL<TDBObject>>;
GlobalContainer.RegisterType<IBaseDAL<TDBCRM>>;

Using in project:

I need to resolve now IBaseDAL, but could not find how do it. Only below ugly approach work

DM := GlobalContainer.Resolve('i_BaseDAL.IBaseDAL<u_DB.TDBObject>@TBaseDAL<u_DBCRM.TDBCRM>').AsInterface as IBaseDAL<TDBObject>;

but I was hoping that below will work :) -

DM := GlobalContainer.Resolve(IBaseDAL<TDBCRM>);

Please advise how could it be resolved correctly?


Solution

  • Edit: I just noticed that somehow the interface table does not contain generic interfaces so you have to explicitly register them as explained below.

    First you need to register an implementation and not just an interface.

    GlobalContainer.RegisterType<TBaseDAL<TDBObject>>;
    GlobalContainer.RegisterType<TBaseDAL<TDBCRM>>;
    GlobalContainer.Build;
    

    The container will inspect the class you registered and register all implemented interfaces (except IInterface) so it will know about IBaseDAL<TDBObject> and IBaseDAL<TDBCRM>.

    If your class might implement some interfaces you don't want the container to know you have to register explicit:

    GlobalContainer.RegisterType<IBaseDAL<TDBObject>, TBaseDAL<TDBObject>>;
    GlobalContainer.RegisterType<IBaseDAL<TDBCRM>, TBaseDAL<TDBCRM>>;
    GlobalContainer.Build;
    

    Then you can resolve:

    GlobalContainer.Resolve<IBaseDAL<TDBCRM>>;
    

    By the way, are you sure your class definition should not be as follows?

    type
      TBaseDAL<T: TDBObject, constructor> = class(TInterfacedObject, IBaseDAL<T>)