2011-10-27 98 views
2

我正在使用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

對於這項工作,我認爲將需要一些方法來指定*有* GUID約束。 –

回答

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; 
+0

當'I'沒有GUID時,故障模式是什麼? –

+0

GUID爲空({00000000-0000-0000-0000-000000000000}),但有趣的是支持仍然返回True。 –

+0

人們只能猜測在這種情況下'intf'中會出現什麼。 –

相關問題