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: TMemoryStream); var size: LongInt; begin size := Length(Str)*sizeof(char); stream.Write(size, Sizeof(LongInt)); stream.Write(Str[1], size); end; var Stream: TMemoryStream; cnt: integer; i: integer; begin Stream := TMemoryStream.Create(); try cnt := Length(Message); i := Stream.Write(Message[1], cnt*SizeOf(char)); i := 0; stream.Write(i, sizeof(i)); 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; SetLength(Result, Stream.Size div sizeof(char)); Stream.Seek(0, soFromBeginning); i := Stream.Read(Result[1], Stream.Size); 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: TMemoryStream): string; var Size: LongInt; begin stream.Read(size, Sizeof(size)); SetLength(result, Size div SizeOf(char)); stream.Read(Result[1], size); end; var Stream: TMemoryStream; i, cnt: integer; begin Clear; Stream := TMemoryStream.Create(); cnt := Length(Value)*SizeOf(char); Stream.Write(Value[1], cnt); try Message := Pchar(Value); if Stream.Size < Length(Message)*SizeOf(char) + sizeof(integer) then exit; Stream.Seek(Length(Message)*SizeOf(char) + sizeof(integer), 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.