gpt4 book ai didi

信号R : Using base type messages between client and hub

转载 作者:行者123 更新时间:2023-12-02 14:29:46 25 4
gpt4 key购买 nike

我对 SignalR 还很陌生,所以我会尽量说得清楚。这是我想要实现的目标:

1.Create self-hosted web application using SignalR
2.Create WPF rich client which will communicate with above-mentioned server app.
3.Use strongly typed request/response messages which inherit from base types respectively to pass data from client to server and vice-versa.

以下是我的请求/响应消息的一些定义:

//Base request message
public class HubRequestMessageBase
{

}

//Base response message
public class HubResponseMessageBase
{
public bool Success { get; set; }
public Exception Error { get; set; }
}

//Request message to query node by name
public class QueryNodeRequest : HubRequestMessageBase
{
public string Name { get; set; }
public Guid Identifier { get; set; }
}

//Response message carrying metadata for the specified node
public class QueryNodeResponse : HubResponseMessageBase
{
public NodeMetadata NodeMetadata { get; set; }
}

现在,如果我按如下方式定义服务器方法:

//Main method for handling client requests
public void HandleClientRequest(HubRequestMessageBase message)
{
//Omitted for brevity
}

并从客户端调用服务器方法,如下所示:

internal async void QueryNode(string name)
{
QueryNodeRequest req = new QueryNodeRequest();
req.Name = name;

await HubProxy.Invoke("HandleClientRequest", new object[] { req });
}

在服务器端,我仍然在 HandleClientRequest 方法中获取 HubRequestMessageBase 作为 message 参数类型,而不是 QueryNodeRequest现在,经过一番挖掘,我了解到 SignalR 默认情况下不处理多态性(或者消息未正确序列化/反序列化,以键入我期望的类型 - 在这种情况下 QueryNodeRequest 继承自 <强>HubRequestMessageBase)。

我的问题是:是否有可能利用客户端和服务器上的 JsonSerializer 设置以某种方式完成此任务?请注意,我已经尝试了以下代码(以及一些变体),但没有成功(在服务器上):

GlobalHost.DependencyResolver.Register(typeof(JsonSerializer),
() => JsonSerializer.Create(new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
}));

提前致谢!

干杯,西瓦

最佳答案

我已经能够解决这个问题了。

问题的根本原因是 signalr 代码库中的这一行 https://github.com/SignalR/SignalR/blob/dev/src/Microsoft.AspNet.SignalR.Core/Json/JRawValue.cs#L28其中 signalr 使用默认序列化器并且不允许您注入(inject)自己的序列化器。

我的解决方案是通过将参数类型设置为 JObject 来绕过该序列化程序然后通过使用序列化器的自定义实例和基于 JObject 的 JTokenReader 将该 JObject 转换为集线器本身的具体类型

我的集线器方法(请注意,ClientCommand 是我所有可能的命令的抽象基类)

public async Task DispatchCommand(Envelope envelope)
{
var settings = new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects
};
var serializer = JsonSerializer.Create(settings);
var c = (ClientCommand) serializer.Deserialize(new JTokenReader(envelope.Command), typeof(ClientCommand));

await commandDispatcher.SendCommand(c);
}

信封类型

public sealed class Envelope
{
public JObject Command { get; set; }
}

通过在 JsonSerializer 上使用 TypeNameHandling = TypeNameHandling.Objects,我所需要做的就是在从客户端发送的对象中包含 $type 属性。

关于信号R : Using base type messages between client and hub,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39988748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com