我正在使用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,但是没有办法将此要求指定为约束。
一种可能的解决方法可能是不使用通用抽象类并在验证器中强制转换接口,但我只是想知道是否有人知道如何在不进行强制转换的情况下执行此操作。
答案 0 :(得分:1)
以下似乎有效:
uses
SysUtils, TypInfo;
{ TValidator<I> }
procedure TValidator<I>.Validate(const aEntity: IModelEntity; aResult: string);
var
intf: I;
begin
if not Supports(aEntity, GetTypeData(TypeInfo(I))^.Guid, intf) then
Exit;
DoValidate(intf, aResult);
end;