Если вы используете библиотеку Newtonsoft.Json, то вам подойдёт следующий класс конверта сообщения (а если вы её не используете, то пора начинать использовать):
class Message
{
public string route;
public JToken data;
}
Также можно использовать в качестве конверта JObject.
После того, как вы определитесь с обработчиком, JToken можно десериализовать в конкретный тип данных:
interface IRouteHandler
{
void Handle(JToken data);
}
abstract class RouteHandler<T> : IRouteHandler
{
protected abstract void Handle(T data);
void IRouteHandler.Handle(JToken data)
{
this.Handle(data.ToObject<T>());
}
}
// Пример конкретного обработчика
class FooHandler : RouteHandler<Foo>
{
protected override void Handle(T data)
{
// …
}
}
Если вам ближе не ООП, а делегаты - вот так можно "замкнуть" конкретный тип в делегате:
delegate void RouteHandler(JToken data);
delegate void RouteHandler<T>(T data);
static class Route
{
public RouteHandler For<T>(RouteHandler<T> handler)
=> data => handler(data.ToObject<T>());
}
// …
Dictionary<string, RouteHandler> routes = new
{
{ "foo", Route.For<Foo>(() =>
{
// …
}
)},
{ "bar", Route.For<Bar>(() =>
{
// …
}
)},
};
Наконец, если хочется чего-то совсем примитивного и без лишних сущностей, можно сами классы сообщений сделать одновременно и обработчиками:
interface IRouteHandler
{
void Execute();
}
delegate void RouteHandler(JToken data);
static class Route
{
public RouteHandler For<T>() where T : IRouteHandler
=> data => data.ToObject<T>().Execute();
}
// …
Dictionary<string, RouteHandler> routes = new
{
{ "foo", Route.For<Foo>() },
{ "bar", Route.For<Bar>() },
};
Отмечу, что более в современной System.Text.Json вместо JToken для тех же целей нужно использовать тип JsonElement, а дальнейшая десериализация вместо ToObject делается через JsonSerializer.Deserialize<T>. В остальном всё так же.
System.Text.Jsonнедоступен в Unity. А чтобы не творить такие костыли сJToken, естьTypeNameHandling. – aepot Mar 01 '23 at 10:42