unit BizSchemaClient; interface uses Classes, SchemaClient_Intf; type IBizCustomers = interface(ICustomers) ['{63BAECDD-6091-4A86-BA58-E6FFD5330240}'] end; TBizCustomersDataTableRules = class(TCustomersDataTableRules, IBizCustomers) end; IBizOrders = interface(IOrders) ['{E43D1B71-EEF0-4805-9F1E-EE032353BD0F}'] end; TBizOrdersDataTableRules = class(TOrdersDataTableRules, IBizOrders) end; TBizErrorMessageItem = class public Field: string; ErrorMessage: string; end; TBizErrorMessage = class private FMessage: string; FList: TList; function GetItems(Index: integer): TBizErrorMessageItem; function GetCount: integer; function GetAsString: string; procedure SetAsString(const Value: string); public constructor Create; destructor Destroy; override; function Add(AField: string; AErrorMessage: string): integer; procedure Clear; property ItemCount: integer read GetCount; property Message: string read FMessage write FMessage; property Items[Index: integer]: TBizErrorMessageItem read GetItems; property AsString: string read GetAsString write SetAsString; end; implementation uses uDADataTable, Variants; { TBizErrorMessage } function TBizErrorMessage.Add(AField: string; AErrorMessage: string): integer; var Aitem: TBizErrorMessageItem; begin Aitem := TBizErrorMessageItem.Create; Aitem.Field := AField; Aitem.ErrorMessage := AErrorMessage; Result := FList.Add(AItem); end; procedure TBizErrorMessage.Clear; var i: integer; begin for i := 0 to Flist.Count - 1 do TBizErrorMessageItem(FList[i]).Free; FList.Clear; end; constructor TBizErrorMessage.Create; begin inherited; FList := TList.Create; end; destructor TBizErrorMessage.Destroy; begin Clear; Flist.Free; inherited; end; function TBizErrorMessage.GetAsString: string; procedure WriteStringToStream(Str: string; Stream: TStringStream); var size: integer; begin size := Length(Str); stream.Write(size, Sizeof(integer)); stream.WriteString(Str); end; var Stream: TStringStream; cnt: integer; i: integer; begin Stream := TStringStream.Create(''); try Stream.WriteString(Message); i := 0; stream.Write(Byte(i), 1); cnt := GetCount; stream.Write(cnt, SizeOf(cnt)); for i := 0 to cnt - 1 do with Items[i] do begin WriteStringToStream(Field, Stream); WriteStringToStream(ErrorMessage, Stream); end; Result := Stream.DataString; finally Stream.Free; end; end; function TBizErrorMessage.GetCount: integer; begin Result := FList.Count; end; function TBizErrorMessage.GetItems(Index: integer): TBizErrorMessageItem; begin Result := TBizErrorMessageItem(FList[Index]); end; procedure TBizErrorMessage.SetAsString(const Value: string); function ReadStringToStream(Stream: TStringStream): string; var Size: integer; begin stream.Read(size, Sizeof(integer)); Result := stream.ReadString(size); end; var Stream: TStringStream; i, cnt: integer; begin Clear; Stream := TStringStream.Create(Value); try Message := Pchar(Value); if Stream.Size < Length(Message) + 1 then exit; Stream.Seek(Length(Message) + 1, soFromBeginning); stream.Read(cnt, SizeOf(cnt)); for i := 0 to cnt - 1 do with Items[Add('', '')] do begin Field := ReadStringToStream(Stream); ErrorMessage := ReadStringToStream(Stream); end; finally Stream.Free; end; end; initialization RegisterDataTableRules('Customers.ClientRules', TBizCustomersDataTableRules); RegisterDataTableRules('Orders.ClientRules', TBizOrdersDataTableRules); end.