2010-05-26 15 views
5

Attualmente sto creando soap wrappers per alcune funzioni di Delphi in modo che possiamo facilmente usarle da PHP, C# e Delphi.Come esporre un tipo di set Delphi tramite Soap

Mi chiedo quale sia il modo migliore per esporre i set.

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; 

Attualmente sto avvolgendolo in questo modo per il server di sapone:

type 
    TCountryArray = array of TCountry; 

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

Funziona, ma ho bisogno di scrivere un sacco di codice inutile e brutto per convertire set -> array e array -> set.

C'è un modo più semplice, più elegante o più generico per farlo?

risposta

2

È possibile utilizzare TypInfo e utilizzare un po 'di fusione intelligente.

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; 

Quindi utilizzare come:

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; 

Sarà necessario selezionare la fusione corretta in base alla dimensione della enum TCountry. Se ha 8 membri sarà un Byte, qualsiasi più grande e sarà un intero. In ogni caso, Delphi si lamenterà del cast di Byte (Paesi) o Integer (Paesi) quando si sbaglia.

Nota: Le funzioni ora includono il TypeInfo di TCountry: gli elementi di TCountrySet. Potrebbero essere cambiati per prendere TypeInfo (TCountrySet). Tuttavia ciò significherebbe che le funzioni elaborano quali elementi sono presenti nel set e semplicemente non ho avuto il tempo o l'inclinazione per farlo ancora.

1

Il sapone deve essere utilizzato in modo indipendente dalla piattaforma e dal linguaggio: progetterei tutti gli oggetti di trasferimento dati (DTO) basati su tipi semplici, ad es. array of string, senza caratteristiche specifiche della lingua. Quindi associare il DTO agli oggetti di business corrispondenti. Questo ti darà anche un 'livello anticorruzione'.

Problemi correlati