design suggestion for a message decoder in delphi
Posted
by stanleyxu2005
on Stack Overflow
See other posts from Stack Overflow
or by stanleyxu2005
Published on 2010-04-06T03:23:02Z
Indexed on
2010/04/06
3:33 UTC
Read the original article
Hit count: 329
Hi All,
I want to implement a RPC module. Different requests are encoded as JSON objects. They will be decoded and then be handled by a request handler. At last a corresponding response will be returned. The demo code looks as follows:
type
IRequestHandler = interface
function Handle(const Request: TAaaRequest): TResponse;
function Handle(const Request: TBbbRequest): TResponse;
end;
TDecoder = class
class function Decode(const Json: TJsonObject; const RequestHandler: IRequestHandler): TResponse;
end;
class function TDecoder.Decode(const Json: TJsonObject; const RequestHandler: IRequestHandler): TResponse;
var
Method: string;
Request: TObject;
begin
Method := Json['method'].AsString;
if (Method = TAaaRequest.ClassName) then
begin
Request := TAaaRequest.FromJSON(Json); // Casted as TObject
if Request <> nil then
begin
Result := RequestHandler.Handle(TAaaRequest(Request));
Request.Free;
end;
end
else if (Method = TBbbRequest.ClassName) then
begin
Request := TBbbRequest.FromJSON(Json); // Casted as TObject
if Request <> nil then
begin
Result := RequestHandler.Handle(TBbbRequest(Request));
Request.Free;
end;
end
else
Result := CreateErrorResponse('Unknown method: ' + Json.ToString);
end;
According to the code, the handling of different request types are very similar. If I have 100 different request types, I have to copy and paste the above code block 100 times. This is not clever. I am looking for a better way to do the same logic. My imagination is as follows:
TDecoder = class
private
FRequestTypes: TDictionary<string, TClassInfo>; // Does this work?
public
constructor Create;
destructor Destroy; override;
function Decode(const Json: TJsonObject; const RequestHandler: IRequestHandler): TResponse;
end;
constructor TDecoder.Create;
begin
FRequestTypes := TDictionary<string, TClassInfo>.Create;
FRequestTypes.Add(TAaaRequest.ClassName, TAaaRequest); // Does this work?
FRequestTypes.Add(TBbbRequest.ClassName, TBbbRequest);
end;
destructor TDecoder.Destroy;
begin
FRequestTypes.Free;
inherited;
end;
function TDecoder.Decode(const Json: TJsonObject; const RequestHandler: IRequestHandler): TResponse;
var
Method: string;
Info: TClassInfo;
Request: TObject;
begin
Method := Json['method'].AsString;
if FRequestTypes.ContainsKey(Method) then
begin
// An universal way
Info := FRequestTypes[Method];
Request := Info.FromJSON(Json); // Casted as TObject
if Request <> nil then
begin
Result := RequestHandler.Handle(Info(Request)); // Casted to corresponding class type (e.g. TAaaRequest or TBbbRequest)
Request.Free;
end;
end
else
Result := CreateErrorResponse('Unknown method: ' + Json.ToString);
end;
I do not know, if I can write an universal way to handle a great number of different request types. Development environment Delphi 2010.
Any hint is appreciated.
© Stack Overflow or respective owner