Ваша вторая попытка очень близка. Вам не хватает только нескольких деталей.
Если вы использовали составной тип TClassInfo
, вам нужно определить метакласс для представления классов вашего запроса. Я предполагаю, что TAaaRequest
и TBbbRequest
(и 100 других классов запросов) все происходят от некоторого базового TRequest
класса. Определите TRequestClass
как это:
type
TRequestClass = class of TRequest;
Метод FromJSON
делает что-то свое для каждого класса, верно? Если это так, то это должно быть виртуальным. (Если метод делает то же самое в каждом классе, тогда он не может быть виртуальным, несмотря на то, что другие могут вам сказать.) Вам не нужно приводить тип результата к конструктору ; просто объявите Info
как TRequest
вместо TObject
.
Самое большое изменение, которое вам нужно сделать, - это интерфейс IRequestHandler
. Поскольку каждый из ваших объектов является TRequest
, будет неуклюже отправлять правильный интерфейсный метод без гигантской if
- else
лестницы для проверки каждого возможного класса.
Вместо этого снова используйте виртуальную диспетчеризацию. Присвойте каждому TRequest
объекту виртуальный Handle
метод, чтобы объявление класса выглядело так:
type
TRequest = class
public
constructor FromJSON(const json: string);
function Handle: TResponse; virtual; abstract;
end;
Реализация Handle
для каждого потомка, и все готово. В конечном итоге, интерфейс IRequestHandler
может исчезнуть. Вы уже написали возможность обработки в каждом из классов запросов. Вам не нужен один класс для представления запроса и другой класс для его обработки.
Если вы хотите иметь отдельный класс обработки, то вы можете либо пойти с тем, что у вас уже есть, где у вас будет большое условное решение, какой метод IRequestHandler
вы будете вызывать, или у вас много запросов Все объекты -handler реализуют один и тот же интерфейс, и вы решаете, какой из них создать таким же образом, как вы решаете, какой класс запроса создать. Затем вы передаете объект request объекту request-handler и позволяете им работать вместе.
Например, определите интерфейс вашего обработчика:
type
IRequestHandler = interface
function Handle(request: TRequest): TResponse;
end;
Регистрируйте обработчики так же, как вы регистрируете запросы:
// Use the same names as the requests, but a different dictionary
FRequestHandlers.Add(TAaaRequest.ClassName, TAaaHandler);
FRequestHandlers.Add(TBbbRequest.ClassName, TBbbHandler);
Создайте обработчики, как вы делаете запросы:
HandlerType := FRequestHandlers[Method];
HandlerObject := HandlerType.Create;
if not Supports(HandlerObject, IRequestHandler, Handler) then
exit;
Затем передайте запрос обработчику:
Result := Handler.Handle(Request);