I am trying to write a common messaging system for Delphi and .NET. The system allows you to define messages as simple objects, and message handlers are defined as anonymous methods that act on these objects.
Objects are converted to JSON and transferred between applications running on the same computer. Each application maintains a list of handlers that understand specific types of messages.
My class has a number of parameterized registration methods. Some accept one type parameter. Some take a couple of parameters in which one represents the request object and the other represents the response object. Here's what the registration of the Request / Response handler looks like:
procedure TTelegraph.RegisterRequestHandler<TRequest, TResponse> (requestTypeToHandle: string; handler: TFunc<TRequest, TResponse>); begin FRequestHandlers.Add(requestTypeToHandle, TRequestHandler<TRequest, TResponse>.Create(handler, TRequest, TResponse)); end;
FRequestHandlers is a TDictionary<string,TRequestHandler> . The registration method is called like this:
FTelegraph.RegisterRequestHandler<TTestRequest, TTestResponse>('My Request', function(x: TTestRequest): TTestResponse begin Result := TTestResponse.Create; Result.Number := x.Number; Result.Message := Format('Received: %s', [x.Message]); end);
The generic TRequestHandler<T1,T2> is the DTO that wraps the handler along with the types TRequest and TResponse . It inherits from the non-generic TRequestHandler . I'm not sure if there is a better way to do this, but that was the only way I could think of saving multiple unrelated types in one collection.
It all works fine. The problem is getting a request message. C # code for processing request messages is as follows:
private void ProcessRequestTelegram(Telegram request) { var requestType = _RequestHandlers[request.MessageType].RequestType; var typedRequest = JsonConvert.DeserializeObject(request.Payload, requestType); var result = _RequestHandlers[request.MessageType].Handler.DynamicInvoke(typedRequest); var jsonPayload = JsonConvert.SerializeObject(result); var response = new Telegram() { Payload = jsonPayload, CorrelationID = request.CorrelationID, Template = TelegramTemplateEnum.Response, SenderWindowHandle = _LocalWindowHandle.ToInt32(), RecipientWindowHandle = _MessageRecipient.ToInt32(), MessageType = request.MessageType }; var jsonResponse = JsonConvert.SerializeObject(response); var resultCode = _Messaging.SendMessage(_MessageRecipient, jsonResponse); CheckIfSendMessageErrorOccurred(resultCode); }
In the above code, RequestType is of type Type .
But for life, I canβt come up with the equivalent of Delphi. I get to attempt to deserialize the request. Download, and I'm stuck on how to pass a JSON type parser to convert the payload. I tried various ways to store TRequest and TResponse in the RequestType and ResponseType TRequestHandler : TTypeInfo , TRTTIType and currently TClass . But nothing seems useful to me to switch to TJson.JsonToObject . It has a common overload that takes a type parameter for a return type, but apparently you cannot use TClass as a type parameter.