У меня есть клиент, который отправляет запросы на сервер. Запросы и ответы также являются игровыми событиями, поэтому я могу отправлять запросы и ответы туда, где они нужны в коде:
public class Message {}
public interface IOnlineRequest : IGameEvent {}
public interface IOnlineResponse : IGameEvent {}
public abstract class OnlineRequest<T> : Message, IOnlineRequest {
public abstract T Request { get; set; }
}
public abstract class OnlineResponse<T> : Message, IOnlineResponse {
public abstract T Response { get; set; }
}
public sealed class OPingRequest : OnlineRequest<PingRequest>
{
public override PingRequest Request { get; set; }
}
public sealed class OPingResponse : OnlineResponse<PingResponse>
{
public override PingResponse Response { get; set; }
}
Существует класс менеджера, который имеет следующие члены:
private SortedDictionary<int, IOnlineRequest> requests_ = new SortedDictionary<int, IOnlineRequest>();
private SortedDictionary<int, IOnlineResponse> responses_ = new SortedDictionary<int, IOnlineResponse>();
Я повторяю запросы и включаю тип (эта часть мне не нравится, и я хотел бы переписать ее с помощью OOP):
bool error = false;
foreach (var request in requests_)
{
if (!error)
{
switch (request.Value)
{
case OPingRequest req:
error = await ProcessRequest<PingRequest, PingResponse, OPingResponse>(request.Key, req, Profile.PingAsync);
break;
case OKeepAliveRequest req:
error = await ProcessRequest<KeepAliveRequest, KeepAliveResponse, OKeepAliveResponse>(request.Key, req, Profile.KeepAliveAsync);
break;
case OLoginRequest req:
error = await ProcessRequest<LoginRequest, LoginResponse, OLoginResponse>(request.Key, req, Profile.LoginAsync);
break;
case OCounterRequest req:
error = await ProcessRequest<CounterRequest, CounterResponse, OCounterResponse>(request.Key, req, Profile.CounterAsync);
break;
default:
throw new NotImplementedException("Add code for your request type above!");
}
}
else
{
break; // Break out of foreach
}
}
И это обобщение c Функция ProcessRequest:
private async Task<bool> ProcessRequest<T, U, V>(int num, OnlineRequest<T> req, Func<T, CancellationToken, Task<U>> func)
where T : class, IMessage<T>
where U : class, IMessage<U>
where V : OnlineResponse<U>, new()
{
req.State = new RequestState();
U resp = null;
try
{
resp = await func(req.Request);
req.State.Status = RequestStatus.Success;
req.State.Message = "";
}
catch (Exception ex)
{
req.State.Status = RequestStatus.Failed;
req.State.Message = ex.ToString();
}
responses_.Add(num, new V { State = req.State, Response = resp });
return true;
}
Трудно повторно реализовать это в OOP, в основном потому, что такие типы, как PingRequest, PingResponse
, являются конкретными типами, и они генерируются, поэтому у меня нет выбора и я не могу измените их.
Я бы хотел добиться:
bool error = false;
foreach (var request in requests_)
{
if (!error)
{
error = request.Process();
}
else
{
break;
}
}