2010-05-26 1 views
5

В настоящее время я создаю мыльные оболочки для некоторых функций Delphi, чтобы мы могли легко использовать их из PHP, C# и Delphi.Как установить тип набора Delphi с помощью мыла

Интересно, какой лучший способ выставить наборы.

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; 

Я сейчас окружив его, как это для сервера мыло:

type 
    TCountryArray = array of TCountry; 

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

Это работает, но мне нужно написать много бесполезного и некрасивого кода для преобразования наборов -> массивы и массивы -> наборы.

Есть ли более простой, более элегантный или более общий способ сделать это?

ответ

2

Вы можете использовать TypInfo и использовать немного умного литья.

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; 

Затем используйте как:

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; 

Вам нужно будет выбрать правильный кастинг на основе размера перечисления TCountry. Если у него 8 членов, это будет Byte, любое большее и будет Integer. В любом случае, Delphi будет жаловаться на актеры Байт (Страны) или Целое (Страны), когда вы ошибетесь.

Обратите внимание: Теперь функции TypeInfo of TCountry - элементы TCountrySet. Их можно было изменить, чтобы взять TypeInfo (TCountrySet). Однако это означало бы, что функции определяют, какие элементы находятся в наборе, и у меня просто не было времени или желания сделать это.

1

Мыло должно использоваться в агностическом режиме платформы и языка - я бы проектировал все объекты передачи данных (DTO) на основе простых типов, например. array of string, без особенностей языка. Затем сопоставьте DTO с соответствующими бизнес-объектами. Это также даст вам «антикоррупционный слой».

 Смежные вопросы

  • Нет связанных вопросов^_^