【发布时间】:2020-04-06 08:33:02
【问题描述】:
我有一个向服务器发送请求的客户端。请求和响应也是游戏事件,因此我可以将请求和响应发送到代码中需要它们的任何位置:
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
}
}
这是通用的 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;
}
}
【问题讨论】:
-
您的原始实现中有多少个 switch case?如果只有一个,应该没问题。如果有很多,请制作一个策略模式和一个
Dictionary<type,Func>来替换 switch case。 -
@LouisGo 我估计会有 100 多种请求类型