2015-07-01 21 views
7

Tôi đang cố viết một hệ thống gửi tin nhắn chung cho Delphi và .NET. Hệ thống cho phép các thông điệp được định nghĩa là các đối tượng đơn giản và các trình xử lý tin nhắn được định nghĩa là các phương thức nặc danh hoạt động trên các đối tượng đó.Làm cách nào để lưu trữ các tham số kiểu của một phương thức được tham số hóa và sau đó sử dụng chúng để chuyển đổi một đối tượng JSON thành một đối tượng thuần túy của kiểu generic?

Các đối tượng được chuyển đổi thành JSON và chuyển giữa các ứng dụng đang chạy trên cùng một máy. Mỗi ứng dụng duy trì một danh sách các trình xử lý để hiểu các loại thông báo cụ thể.

Lớp học của tôi có một số phương pháp đăng ký tham số. Một số có tham số kiểu đơn. Một số có một cặp tham số trong đó một đại diện cho một đối tượng yêu cầu và một đối tượng phản hồi khác. Dưới đây là những gì yêu cầu đăng ký xử lý Yêu cầu/Trả lời như sau:

procedure TTelegraph.RegisterRequestHandler<TRequest, TResponse> 
    (requestTypeToHandle: string; handler: TFunc<TRequest, TResponse>); 
begin 
    FRequestHandlers.Add(requestTypeToHandle, 
    TRequestHandler<TRequest, TResponse>.Create(handler, 
    TRequest, 
    TResponse)); 
end; 

FRequestHandlersTDictionary<string,TRequestHandler>. Phương pháp đăng ký được gọi là như vậy:

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); 

các generic TRequestHandler<T1,T2> là một DTO mà kết thúc tốt đẹp xử lý cùng với các loại TRequestTResponse. Nó được kế thừa từ không chung chung TRequestHandler. Tôi không chắc chắn nếu có một cách tốt hơn để đi về việc này, nhưng nó là cách duy nhất tôi có thể nghĩ đến để lưu trữ nhiều loại không liên quan trong một bộ sưu tập duy nhất.

Tất cả điều này dường như hoạt động tốt. Vấn đề là khi nhận được một tin nhắn yêu cầu. Mã C# để xử lý các thông điệp yêu cầu trông như thế này:

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); 
} 

Trong đoạn mã trên RequestType là loại Type.

Nhưng đối với cuộc sống của tôi, tôi không thể nghĩ ra tương đương Delphi. Tôi nhận được như xa như cố gắng deserialize request.Payload và tôi bị mắc kẹt tại làm thế nào để vượt qua các phân tích cú pháp JSON loại để chuyển đổi trọng tải vào. Tôi đã thử nhiều cách khác nhau để lưu trữ TRequestTResponse trong thuộc tính RequestType và ResponseType của TRequestHandler: TTypeInfo, TRTTIType và hiện tại TClass. Nhưng dường như không có gì cho tôi bất cứ điều gì hữu ích để vượt qua TJson.JsonToObject. Nó có một quá tải chung mà có một tham số kiểu cho kiểu trả về nhưng dường như bạn không thể sử dụng một tham số kiểu TClass.

+0

Nó không phải là tất cả rõ ràng với tôi rằng các generics đang làm bạn bất kỳ tốt ở đây. Điều này cảm thấy giống như một cái gì đó mà bạn muốn ràng buộc thời gian chạy chứ không phải là thời gian biên dịch. –

+0

Các generics có chủ yếu để một nhà phát triển thiết kế một tin nhắn mới không cần phải kế thừa từ một lớp cụ thể hoặc thực hiện một giao diện cụ thể. Họ chỉ cần cung cấp một lớp mới và một người xử lý mà biết phải làm gì với nó.Trong mọi trường hợp, thư viện này được thiết kế bởi một đồng nghiệp sử dụng C# và tôi đã chuyển nó sang Delphi. Tôi đã cố gắng giữ API công khai càng gần càng tốt để triển khai C#. –

+0

Tôi không thực sự thấy lý do tại sao generics là cần thiết cho điều đó. Và bạn bị ràng buộc bởi phải khởi tạo tất cả các kiểu generic tại thời gian biên dịch. –

Trả lời

2

Bạn không thể sử dụng TJson.JsonToObject<T> tại thời điểm gọi điện thoại này, bạn không có chung T. Nhìn vào mã của phương pháp này và bạn thấy rằng T đang được chuyển đến TJSONUnMarshal.CreateObject. Vì vậy, trong trường hợp của bạn, bạn nên lưu trữ số TClass của TRequestTResponse và viết phiên bản TJson.JsonToObject của riêng bạn được chuyển qua số TClass.

Một cách khác là tạo cá thể của bạn trước và sau đó chuyển nó đến số TJson.JsonToObject không có số ClassType của trường hợp đã chuyển và chuyển nó đến TJSONUnMarshal.CreateObject.

+0

TJson là một lớp Delphi sao? Đó là đơn vị trong XE? – PSyLoCKe

Các vấn đề liên quan