Este é o tipo de dica que a gente acha que nunca vai usar.
:D
Eu uso o KBM para construir sistemas em N Camadas: http://www.components4programmers.com/.
Para a construção de um RPC ( estou indo direto ao ponto, em caso de dúvidas sobre o assunto me contacte ) a sugestão é encadear um monte de IF como no exemplo abaixo:
// Master request processor. //-------------------------- function TkbmRPCDatabase.ProcessRequest(const Func:string; const ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant; var afunc : string; begin Self.GerarLog(Format('Func: [%s]',[Func]), 0001, ctLOGGExpert,rlLow); try AFunc:=UpperCase(Func); if AFunc='TESTE' then Result := PerformTESTE(ClientIdent,Args) else Result:=inherited ProcessRequest(Func,ClientIdent,Args); except on E: Exception do begin Self.GerarLog(DescreverException(E),0001, ctLOGGExpert,rlLow ); raise; end; end; end;
Ou seja, se eu tiver n funções, teria que encadear um if..else que na minha opnião fica asqueroso de se dar manutenção além de obviamente não ser "performático".
A solução definitiva apareceu nesse tópico: http://delphi.about.com/cs/adptips2004/a/bltip0204_3.htm
Note o seguinte: O seu método tem que estar na parte published da sua classe. Em outras sessões não rola.
Veja como ficou o código:
// Master request processor. //-------------------------- function TkbmRPC_CSAS.ProcessRequest(const Func:string; const ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant; var sFunc : string; rRoutine : TMethod; _perform : TPerformFunction; begin Self.GerarLog(Format('Executando: [%s] - [%s]',[Func,ClientIdent.RemoteLocation]),322382429,ctLOGInformation,rlMiddle); sFunc := Format('Perform%s',[Func]); rRoutine.Data := Pointer(Self); rRoutine.Code := Self.MethodAddress(sFunc); if (Assigned(rRoutine.Code)) then begin _perform := TPerformFunction(rRoutine); Result := _perform(ClientIdent,Args); end else begin inherited ProcessRequest(Func,ClientIdent,Args); end; end;
Para isso tudo funcionar, tive que criar um tipo especial:
interface uses kbmMWSecurity; type {$M+} ///Usado para permitir uma chamada dinâmica às funções dos RPCs TPerformFunction = function(ClientIdent:TkbmMWClientIdentity; const Args:array of Variant): Variant of object;