How can I avoid repeatedly entering a descendant interface type?

I am creating a framework (for internal use only), which has a common code among 3 4 applications of delphi CRD applications.

A common object in the mi framework is TContext,

TContext = class (IContext) function DB: IDatabase; function CurrentSettings: ISettings; .. end; 

which is passed to the initialization method for many other objects .. example (this will be the application code):

  TCustomer.Initialize(Context: IContext) TProjectList.Initialize(Context: IContext) .. 

Each application has some specific contextual functions (which will be called only from the application code):

  IApp1Context = interface (IContext) procedure DoSomethingSpecificToApp1; procedure DoOtherThing; .. end; 

Therefore, when I create a context, Im creates an IApp1Context and sends it to the initialization methods .. everything is fine from the structure code, the problem is that from the application code I constantly transfer from IContext to IApp1Context to access specific App1 it works .. so that the whole my application code looks like (and its a lot of code like this):

  (FContext as IApp1Context).DoSomethingSpecificToApp1 (FContext as IApp1Context).DoOtherThing; .. 

The thing is clearly applicable, but, in my opinion, it does not read well. Maybe I'm exaggerating; Is there a clever technique for this situation that I don’t know about?

+7
source share
3 answers

Use a temporary variable. Assign it once at the beginning of the method, and then use it where you need it.

 var AppContext: IApp1Context; begin AppContext := FContext as IApp1Context; AppContext.DoSomethingSpecificToApp1; AppContext.DoOtherThing; end; 

Or, since it looks like your IContext object is an object field, make your IApp1Context variable a field of the same object. It can even replace the IContext field, since IApp1Context already provides everything that IContext does.

 procedure TCustomer.Initialize(const Context: IContext); begin FContext := Context; FAppContext := FContext as IApp1Context; // ... end; 
+9
source

What do you think of this possible solution using generics?

pro: there is no need to cast down: generic invades almost every interface and framework class, which makes it more complex.

 // framework // type IContext = interface function DB; .. end; TContext = class (TInterfaedObject, IContext) function DB; .. end; IBusinessObj<T: IContext> = interface procedure Initialize(AContext: T); end; TBusinessObj<T: IContext> = class (TInterfacedObject, IBusinessObj<T>) protected FContext: T; public procedure Initialize(Context: T); virtual; end; procedure TBusnessObj<T>.Initialize(Context: T); begin FContext := Context; FContext.DB.Connect; end; // application // type IApp1Context = interface (IContext) procedure DoSomethingElse; .. end; TApp1Context = class(TContext, IContext, IApp1Context) function DB; procedure DoSomethingElse; end; TCustomer = class(TBusinessObj<IApp1Context>) public procedure Initialize(AContext: IApp1Context); override; end; procedure Start; var C: IBusinessObj<IApp1Context>; begin C := TCustomer.Create; C.Initializate(TApp1Context.Create); .. end; procedure TCustomer.Initialize(AContext: IApp1Context); begin inherited; FContext.DoSomethingElse // here I can use FContext as a IApp1Context.. end; 

Comment, please, thanks!

+2
source

You can also assign a private function AppContext , defined as follows:

 function AppContext : IApp1Context; begin Result := FContext as IApp1Context; end; 

This avoids the declaration of an additional variable and preserves the local location. From the client code, you can simply write:

 AppContext.DoSomethingSpecificToApp1; AppContext.DoOtherThing 
+1
source

All Articles