1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 00:42:55 +08:00

Separate SignalR workaround types away from resolver

This commit is contained in:
Salman Ahmed 2021-11-20 15:11:02 +03:00
parent 0342923408
commit 8b28bf31f6
3 changed files with 45 additions and 33 deletions

View File

@ -17,8 +17,9 @@ namespace osu.Game.Online
public class SignalRDerivedTypeWorkaroundJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) =>
SignalRUnionWorkaroundResolver.BASE_TYPES.Contains(objectType) ||
SignalRUnionWorkaroundResolver.DERIVED_TYPES.Contains(objectType);
SignalRWorkaroundTypes.BASE_DERIVED.Any(t =>
objectType == t.baseType ||
objectType == t.derivedType);
public override object? ReadJson(JsonReader reader, Type objectType, object? o, JsonSerializer jsonSerializer)
{
@ -29,7 +30,7 @@ namespace osu.Game.Online
string type = (string)obj[@"$dtype"]!;
var resolvedType = SignalRUnionWorkaroundResolver.DERIVED_TYPES.Single(t => t.Name == type);
var resolvedType = SignalRWorkaroundTypes.BASE_DERIVED.Select(t => t.derivedType).Single(t => t.Name == type);
object? instance = Activator.CreateInstance(resolvedType);

View File

@ -3,11 +3,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using MessagePack;
using MessagePack.Formatters;
using MessagePack.Resolvers;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
namespace osu.Game.Online
{
@ -20,40 +19,26 @@ namespace osu.Game.Online
public static readonly MessagePackSerializerOptions OPTIONS =
MessagePackSerializerOptions.Standard.WithResolver(new SignalRUnionWorkaroundResolver());
public static readonly IReadOnlyList<Type> BASE_TYPES = new[]
private static readonly IReadOnlyDictionary<Type, IMessagePackFormatter> formatter_map = createFormatterMap();
private static IReadOnlyDictionary<Type, IMessagePackFormatter> createFormatterMap()
{
typeof(MatchServerEvent),
typeof(MatchUserRequest),
typeof(MatchRoomState),
typeof(MatchUserState),
};
IEnumerable<(Type derivedType, Type baseType)> baseDerived = SignalRWorkaroundTypes.BASE_DERIVED;
public static readonly IReadOnlyList<Type> DERIVED_TYPES = new[]
{
typeof(ChangeTeamRequest),
typeof(TeamVersusRoomState),
typeof(TeamVersusUserState),
};
private static IReadOnlyDictionary<Type, IMessagePackFormatter> formatterMapBacking;
private static IReadOnlyDictionary<Type, IMessagePackFormatter> formatterMap => formatterMapBacking ??= new Dictionary<Type, IMessagePackFormatter>
{
{ typeof(TeamVersusUserState), new TypeRedirectingFormatter<TeamVersusUserState, MatchUserState>() },
{ typeof(TeamVersusRoomState), new TypeRedirectingFormatter<TeamVersusRoomState, MatchRoomState>() },
{ typeof(ChangeTeamRequest), new TypeRedirectingFormatter<ChangeTeamRequest, MatchUserRequest>() },
// These should not be required. The fallback should work. But something is weird with the way caching is done.
// This should not be required. The fallback should work. But something is weird with the way caching is done.
// For future adventurers, I would not advise looking into this further. It's likely not worth the effort.
{ typeof(MatchUserState), new TypeRedirectingFormatter<MatchUserState, MatchUserState>() },
{ typeof(MatchRoomState), new TypeRedirectingFormatter<MatchRoomState, MatchRoomState>() },
{ typeof(MatchUserRequest), new TypeRedirectingFormatter<MatchUserRequest, MatchUserRequest>() },
{ typeof(MatchServerEvent), new TypeRedirectingFormatter<MatchServerEvent, MatchServerEvent>() },
};
baseDerived = baseDerived.Concat(baseDerived.Select(t => (t.baseType, t.baseType))).Distinct();
return new Dictionary<Type, IMessagePackFormatter>(baseDerived.Select(t =>
{
var formatter = (IMessagePackFormatter)Activator.CreateInstance(typeof(TypeRedirectingFormatter<,>).MakeGenericType(t.derivedType, t.baseType));
return new KeyValuePair<Type, IMessagePackFormatter>(t.derivedType, formatter);
}));
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
if (formatterMap.TryGetValue(typeof(T), out var formatter))
if (formatter_map.TryGetValue(typeof(T), out var formatter))
return (IMessagePackFormatter<T>)formatter;
return StandardResolver.Instance.GetFormatter<T>();

View File

@ -0,0 +1,26 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
namespace osu.Game.Online
{
/// <summary>
/// A static class providing the list of types requiring workarounds for serialisation in SignalR.
/// </summary>
/// <seealso cref="SignalRUnionWorkaroundResolver"/>
/// <seealso cref="SignalRDerivedTypeWorkaroundJsonConverter"/>
internal static class SignalRWorkaroundTypes
{
internal static readonly IReadOnlyList<(Type derivedType, Type baseType)> BASE_DERIVED = new[]
{
(typeof(ChangeTeamRequest), typeof(MatchUserRequest)),
(typeof(TeamVersusRoomState), typeof(MatchRoomState)),
(typeof(TeamVersusUserState), typeof(MatchUserState)),
(typeof(MatchServerEvent), typeof(MatchServerEvent)),
};
}
}