我正在尝试为Delphi和.NET编写通用的消息传递系统。系统允许将消息定义为普通对象,并将消息处理程序定义为对这些对象起作用的匿名方法。
对象转换为JSON并在同一台机器上运行的应用程序之间传递。每个应用程序都维护一个理解特定消息类型的处理程序列表。
我的班级有许多参数化注册方法。有些采用单一类型参数。有些参数采用一对参数,其中一个表示请求对象,另一个表示响应对象。以下是请求/响应处理程序注册的内容:
procedure TTelegraph.RegisterRequestHandler<TRequest, TResponse>
(requestTypeToHandle: string; handler: TFunc<TRequest, TResponse>);
begin
FRequestHandlers.Add(requestTypeToHandle,
TRequestHandler<TRequest, TResponse>.Create(handler,
TRequest,
TResponse));
end;
FRequestHandlers
是TDictionary<string,TRequestHandler>
。注册方法如下调用:
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);
通用TRequestHandler<T1,T2>
是一个DTO,它包含处理程序以及类型TRequest
和TResponse
。它继承自非通用TRequestHandler
。我不确定是否有更好的方法可以解决这个问题,但这是我能想到的在单个集合中存储多个不相关类型的唯一方法。
这一切似乎都很好。问题是收到请求消息时。处理请求消息的C#代码如下所示:
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);
}
上面的代码RequestType
属于Type
类型。
但是对于我的生活,我无法想出Delphi等同物。我试图反序列化request.Payload,我坚持如何传递JSON解析器类型转换有效负载。我尝试了TRequest
和TResponse
在TRequestHandler
:TTypeInfo
,TRTTIType
和当前TClass
的RequestType和ResponseType属性中的各种存储方式。但似乎没有任何东西可以传递给TJson.JsonToObject
。它有一个泛型重载,它为返回类型提供了一个类型参数,但显然你不能使用TClass
作为类型参数。
答案 0 :(得分:2)
您不能使用TJson.JsonToObject<T>
,因为在调用此项时您没有通用T.查看此方法的代码,您会看到T传递给TJSONUnMarshal.CreateObject
。因此,在您的情况下,您应该存储TClass
TRequest
和TResponse
的{{1}},并编写自己的TJson.JsonToObject
版本,并传递TClass
。
另一种方法是首先创建您的实例,然后将其传递给非通用TJson.JsonToObject
,它将传递的实例的ClassType
传递给TJSONUnMarshal.CreateObject
。