Отправка списка различных объектов через SignalR - PullRequest
1 голос
/ 10 февраля 2020

Каков наилучший способ отправки клиентам списка различных объектов через SignalR?

Когда я использую список объектов с одинаковой базой, клиент получает только свойства базового класса:

class Update { }
class UpdateA { public string PropertyA {get; set;}}
class UpdateB { public string PropertyB {get; set;}}
...
IEnumerable<Update> updates = GetUpdates();
await Clients.Caller.SendAsync("update", updates);

Когда я использую предварительно сериализованные данные в виде строк, serialzier экранирует данные json в виде строк.

IEnumerable<string> updates = GetUpdates();
await Clients.Caller.SendAsync("update", updates);
// data looks like: [ "{...}", "{...}" ]

Нужно ли писать свой собственный serialzier? Как это работает для SignalR в ядре do tnet?

1 Ответ

1 голос
/ 11 февраля 2020

отправка клиентам списка различных объектов с одинаковой базой через SignalR

Вы можете попытаться выполнить требование, создав и используя специальный конвертер, как показано ниже.

В пользовательском конвертере MyConverterWithTypeDiscriminator

public override void Write(Utf8JsonWriter writer, Update value, JsonSerializerOptions options)
{
    writer.WriteStartObject();

    if (value is UpdateA updateA)
    {
        writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.UpdateA);
        writer.WriteString("PropertyA", updateA.PropertyA);
    }
    else if (value is UpdateB updateB)
    {
        writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.UpdateB);
        writer.WriteString("PropertyB", updateB.PropertyB);
    }

    writer.WriteString("UpdatedAt", value.UpdatedAt);

    writer.WriteEndObject();
}

Базовый класс и производные классы

public class Update
{
    public DateTime UpdatedAt { get; set; }
}

public class UpdateA : Update
{
    public string PropertyA { get; set; }
}

public class UpdateB : Update
{
    public string PropertyB { get; set; }
}

При запуске .cs

services.AddSignalR().AddJsonProtocol(options => options.PayloadSerializerOptions.Converters.Add(new MyConverterWithTypeDiscriminator()));

Метод In Hub

var updates = new List<Update>
{
    new UpdateA
    {
        UpdatedAt=DateTime.Now.AddDays(-1),
        PropertyA = "A"
    },
    new UpdateB
    {
        UpdatedAt=DateTime.Now.AddDays(-1),
        PropertyB = "B"
    }
};

await Clients.All.SendAsync("ReceiveUpdate", updates);

Результат теста

enter image description here

Примечание: для реализации пользовательского конвертера, пожалуйста, проверьте эту ссылку: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#support -polymorphi c -десериализация

...