4

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?

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
SpanishBoy
  • 2,105
  • 6
  • 28
  • 51

1 Answers1

2

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>)
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102
  • I was trying class definition in both variants as I described and in your variant, but without changes. Also I tried your recommendation, but got the same error: `[dcc32 Error] fr_CRM.pas(231): E2250 There is no overloaded version of 'Resolve' that can be called with these arguments` – SpanishBoy Jan 10 '15 at 00:27
  • As you mentioned in the other question you called Resolve wrong. You did not type angle brackets but round brackets. Generics require angle brackets (`<` `>` and not `(` `)`) – Stefan Glienke Jan 10 '15 at 12:57
  • Thanks, but with `<` `>` I got `[dcc32 Error] frm_CRM.pas(32): E2010 Incompatible types: "i_BaseDAL.IBaseDAL" and "i_BaseDAL.IBaseDAL"` – YoungMaster Jan 10 '15 at 14:31
  • Not sure, I rechecked advises from Stefan and looks like everything is OK. I am about to prepare test project and push to Google group – SpanishBoy Jan 10 '15 at 14:36