2010-05-26 8 views
5

Je suis en train de créer des wrappers de soap pour certaines fonctions Delphi afin que nous puissions les utiliser facilement depuis PHP, C# et Delphi.Comment exposer un type de set Delphi via Soap

Je me demande quelle est la meilleure façon d'exposer les ensembles.

type 
    TCountry  = (countryUnknown,countryNL,countryD,countryB,countryS,countryFIN,countryF,countryE,countryP,countryPl,countryL); 
    TCountrySet = set of TCountry; 

function GetValidCountrySet(const LicensePlate:string; const PossibleCountriesSet:TCountrySet):TCountrySet; 

Je termine actuellement comme ça pour le serveur de savon:

type 
    TCountryArray = array of TCountry; 

function TVehicleInfo.GetValidCountrySet(const LicensePlate:string; const PossibleCountriesSet:TCountryArray):TCountryArray; 

Il fonctionne, mais je dois écrire beaucoup de code inutile et laid pour convertir ensembles -> tableaux et tableaux -> ensembles.

Existe-t-il un moyen plus facile, plus élégant ou plus générique de faire cela?

Répondre

2

Vous pourriez utiliser TypInfo et utiliser un peu de casting intelligent.

uses TypInfo; 

type 
    TCountry = (cnyNone, cnyNL, cnyD, cnyGB, cnyF, cnyI); 
    TCountrySet = set of TCountry; 

    TCountryArray = array of TCountry; 
    TEnumIntegerArray = array of Integer; 
    TEnumByteArray = array of Byte; 

function GetEnumNamesInSet(const aTypeInfo: PTypeInfo; const aValue: Integer; const aSeparator: string = ','): string; 
var 
    IntSet: TIntegerSet; 
    i: Integer; 
begin 
    Result := ''; 
    Integer(IntSet) := aValue; 
    for i := 0 to SizeOf(Integer) * 8 - 1 do begin 
    if i in IntSet then begin 
     if Result <> '' then begin 
     Result := Result + ','; 
     end; 
     Result := Result + GetEnumName(aTypeInfo, i); 
    end; 
    end; 
end; 

function SetToIntegerArray(const aTypeInfo: PTypeInfo; const aValue: Integer): TEnumIntegerArray; 
var 
    IntSet: TIntegerSet; 
    i: Integer; 
begin 
    SetLength(Result, 0); 
    Integer(IntSet) := aValue; 
    for i := 0 to SizeOf(Integer) * 8 - 1 do begin 
    if i in IntSet then begin 
     SetLength(Result, Length(Result) + 1); 
     Result[Length(Result) - 1] := i; 
    end; 
    end; 
end; 

function SetToByteArray(const aTypeInfo: PTypeInfo; const aValue: Byte): TEnumByteArray; 
var 
    IntSet: TIntegerSet; 
    i: Integer; 
begin 
    SetLength(Result, 0); 
    Integer(IntSet) := aValue; 
    for i := 0 to SizeOf(Byte) * 8 - 1 do begin 
    if i in IntSet then begin 
     SetLength(Result, Length(Result) + 1); 
     Result[Length(Result) - 1] := i; 
    end; 
    end; 
end; 

Ensuite, utilisez comme:

procedure TEnumForm.FillMemo; 
var 
    Countries: TCountrySet; 
// EIA: TEnumIntegerArray; 
    EBA: TEnumByteArray; 
    CA: TCountryArray; 
    i: Integer; 
    cny: TCountry; 
begin 
    Countries := [cnyNL, cnyD]; 
    CountriesMemo.Text := GetEnumNamesInSet(TypeInfo(TCountry), Byte(Countries)); 
// if SizeOf(TCountry) > SizeOf(Byte) then begin 
// EIA := SetToIntegerArray(TypeInfo(TCountry), Integer(Countries)); 
// end else begin 
    EBA := SetToByteArray(TypeInfo(TCountry), Byte(Countries)); 
// end; 
    CountriesMemo.Lines.Add('===='); 
    CountriesMemo.Lines.Add('Values in Array: '); 
// if SizeOf(TCountry) > SizeOf(Byte) then begin 
// CA := TCountryArray(EIA); 
// end else begin 
    CA := TCountryArray(EBA); 
// end; 
    for i := 0 to Length(CA) - 1 do begin 
    CountriesMemo.Lines.Add(IntToStr(Ord(CA[i]))); 
    end; 
    CountriesMemo.Lines.Add('===='); 
    CountriesMemo.Lines.Add('Names in Array: '); 
// if SizeOf(TCountry) > SizeOf(Byte) then begin 
// CA := TCountryArray(EIA); 
// end else begin 
    CA := TCountryArray(EBA); 
// end; 
    for i := 0 to Length(CA) - 1 do begin 
    cny := CA[i]; 
    CountriesMemo.Lines.Add(GetEnumName(TypeInfo(TCountry), Ord(cny))); 
    end; 
end; 

Vous devez sélectionner la coulée appropriée en fonction de la taille de l'ENUM TCountry. S'il a 8 membres, ce sera un octet, un plus grand et un entier. De toute façon, Delphi se plaindra sur le casting de Byte (Pays) ou Integer (Pays) quand vous vous trompez.

Veuillez noter: Les fonctions prennent maintenant TypeInfo de TCountry - les éléments du TCountrySet. Ils pourraient être modifiés pour prendre TypeInfo (TCountrySet). Cependant, cela signifierait que les fonctions détermineraient quels éléments sont dans l'ensemble et je n'ai tout simplement pas eu le temps ou l'envie de le faire pour l'instant.

1

Le savon doit être utilisé de manière indépendante de la plateforme et de la langue - Je conçois tous les objets de transfert de données (DTO) sur la base de types simples, par ex. array of string, sans fonctionnalités spécifiques au langage. Puis mappez le DTO aux objets métier correspondants. Cela vous donnera également une «couche anticorruption».