Я использую Delphi XE2. В настоящее время у меня есть объектно-ориентированная модель, и каждый объект модели может иметь несколько валидаторов. Вот упрощенная реализация обобщенного абстрактного класса валидатора. Конкретные классы валидатора могут переопределять DoValidate, и им не нужно приводить объект модели. Валидатор используется через интерфейс IValidator.
unit ObjectBasedValidator;
interface
uses
System.SysUtils,
System.Generics.Collections;
type
TModelEntity = class
end;
type
IValidator = interface
procedure Validate(aEntity: TModelEntity; aResult: string);
end;
TValidator<T: TModelEntity> = class(TInterfacedObject, IValidator)
private
protected
procedure DoValidate(aEntity: T; aResult: string); virtual; abstract;
public
procedure Validate(aEntity: TModelEntity; aResult: string);
end;
implementation
{ TValidator<T> }
procedure TValidator<T>.Validate(aEntity: TModelEntity; aResult: string);
begin
if not (aEntity is T) then
Exit;
DoValidate(aEntity as T, aResult);
end;
end.
Теперь я пытаюсь изменить объектную модель для интерфейса на основе. Итак, вот обновленный блок валидатора:
unit InterfaceBasedValidator;
interface
type
IModelEntity = interface
end;
type
IValidator = interface
procedure Validate(aEntity: IModelEntity; aResult: string);
end;
TValidator<I: IModelEntity> = class(TInterfacedObject, IValidator)
private
protected
procedure DoValidate(aEntity: I; aResult: string); virtual; abstract;
public
procedure Validate(aEntity: IModelEntity; aResult: string);
end;
implementation
{ TValidator<T> }
procedure TValidator<I>.Validate(aEntity: IModelEntity; aResult: string);
begin
// The next line does not compiles
if not (aEntity is I) then
Exit;
DoValidate(aEntity as I, aResult);
end;
end.
Я добавил комментарий к строке, которая не компилируется. Теперь, очевидно, для универсального типа «I» должен быть определен GUID, чтобы это работало, однако нет способа указать это требование как ограничение.
Возможный обходной путь может заключаться в том, чтобы не использовать универсальный абстрактный класс и приводить интерфейс в валидаторе, но мне просто интересно, есть ли у кого-нибудь идея, как это сделать без приведения.