2011-10-27 7 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はnull({00000000-0000-0000-0000-000000000000})ですが、面白いことにサポートはまだTrueを返します。 –

+0

最終的に 'intf'に出現するものだけを推測することができます。 –

関連する問題