2017-02-09 19:33:59 +01:00
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Delphi MVC Framework
|
|
|
|
//
|
2019-01-08 12:48:27 +01:00
|
|
|
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
|
2017-02-09 19:33:59 +01:00
|
|
|
//
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
//
|
2019-10-10 00:02:02 +02:00
|
|
|
// Collaborators on this file: Ezequiel Juliano Müller (ezequieljuliano@gmail.com)
|
2017-03-01 21:40:57 +01:00
|
|
|
//
|
2017-02-09 19:33:59 +01:00
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
2017-03-01 21:40:57 +01:00
|
|
|
// ***************************************************************************
|
2017-02-09 19:33:59 +01:00
|
|
|
|
2017-02-07 14:08:36 +01:00
|
|
|
unit MVCFramework.Serializer.Commons;
|
|
|
|
|
2017-02-10 14:19:55 +01:00
|
|
|
{$I dmvcframework.inc}
|
|
|
|
|
2017-03-23 18:51:25 +01:00
|
|
|
interface
|
|
|
|
|
2017-02-07 14:08:36 +01:00
|
|
|
uses
|
2017-03-01 21:40:57 +01:00
|
|
|
System.Rtti,
|
|
|
|
System.Classes,
|
|
|
|
System.SysUtils,
|
|
|
|
System.DateUtils,
|
|
|
|
System.TypInfo,
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$IFDEF SYSTEMNETENCODING}
|
2017-03-01 21:40:57 +01:00
|
|
|
System.NetEncoding,
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ELSE}
|
2017-03-01 21:40:57 +01:00
|
|
|
Soap.EncdDecd,
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ENDIF}
|
|
|
|
MVCFramework.Commons,
|
|
|
|
Data.DB;
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
type
|
|
|
|
|
2017-07-16 19:36:44 +02:00
|
|
|
TMVCSerializationType = (stUnknown, stDefault, stProperties, stFields);
|
2017-03-28 14:52:13 +02:00
|
|
|
|
2019-08-28 00:18:30 +02:00
|
|
|
TMVCNameCase = (ncAsIs, ncUpperCase, ncLowerCase, ncCamelCase);
|
2017-03-28 14:52:13 +02:00
|
|
|
|
|
|
|
TMVCDataType = (dtObject, dtArray);
|
|
|
|
|
2017-04-29 23:56:56 +02:00
|
|
|
TMVCDatasetSerializationType = (dstSingleRecord, dstAllRecords);
|
|
|
|
|
2019-08-12 21:48:33 +02:00
|
|
|
TMVCEnumSerializationType = (estEnumName, estEnumOrd);
|
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
TMVCIgnoredList = array of string;
|
|
|
|
|
2019-05-09 20:53:52 +02:00
|
|
|
TMVCSerializationAction<T: class> = reference to procedure(const AObject: T; const Links: IMVCLinks);
|
|
|
|
TMVCSerializationAction = reference to procedure(const AObject: TObject; const Links: IMVCLinks);
|
2019-09-25 09:14:09 +02:00
|
|
|
TMVCDataSetSerializationAction = reference to procedure(const ADataSet: TDataset; const Links: IMVCLinks);
|
2017-04-29 23:56:56 +02:00
|
|
|
|
2017-09-23 15:03:07 +02:00
|
|
|
EMVCSerializationException = class(EMVCException)
|
2017-03-02 12:57:40 +01:00
|
|
|
end;
|
|
|
|
|
2017-09-23 15:03:07 +02:00
|
|
|
EMVCDeserializationException = class(EMVCException)
|
2017-02-08 11:42:05 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
MVCValueAsTypeAttribute = class(TCustomAttribute)
|
2017-02-09 11:24:18 +01:00
|
|
|
private
|
2017-03-01 21:40:57 +01:00
|
|
|
FValueTypeInfo: PTypeInfo;
|
2017-03-28 14:52:13 +02:00
|
|
|
protected
|
|
|
|
{ protected declarations }
|
2017-02-09 11:24:18 +01:00
|
|
|
public
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor Create(AValueTypeInfo: PTypeInfo);
|
|
|
|
function ValueTypeInfo: PTypeInfo;
|
2017-02-09 11:24:18 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
MVCDoNotSerializeAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
{ private declarations }
|
|
|
|
protected
|
|
|
|
{ protected declarations }
|
|
|
|
public
|
|
|
|
{ public declarations }
|
|
|
|
end;
|
2017-02-10 14:19:55 +01:00
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
MVCSerializeAsStringAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
{ private declarations }
|
|
|
|
protected
|
|
|
|
{ protected declarations }
|
|
|
|
public
|
|
|
|
{ public declarations }
|
|
|
|
end;
|
2017-03-01 21:40:57 +01:00
|
|
|
|
|
|
|
MVCNameCaseAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
FKeyCase: TMVCNameCase;
|
|
|
|
function GetKeyCase: TMVCNameCase;
|
2017-03-28 14:52:13 +02:00
|
|
|
protected
|
|
|
|
{ protected declarations }
|
2017-03-01 21:40:57 +01:00
|
|
|
public
|
|
|
|
constructor Create(const AKeyCase: TMVCNameCase);
|
|
|
|
property KeyCase: TMVCNameCase read GetKeyCase;
|
2017-02-10 14:19:55 +01:00
|
|
|
end;
|
|
|
|
|
2017-04-13 12:46:37 +02:00
|
|
|
MapperJSONNaming = MVCNameCaseAttribute deprecated 'Use MVCNameCaseAttribute';
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
MVCNameAsAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
FName: string;
|
|
|
|
function GetName: string;
|
2017-03-28 14:52:13 +02:00
|
|
|
protected
|
|
|
|
{ protected declarations }
|
2017-03-01 21:40:57 +01:00
|
|
|
public
|
|
|
|
constructor Create(const AName: string);
|
2017-05-25 12:30:08 +02:00
|
|
|
property name: string read GetName;
|
2017-03-01 21:40:57 +01:00
|
|
|
end;
|
2017-02-09 19:33:59 +01:00
|
|
|
|
2017-04-26 14:39:18 +02:00
|
|
|
MapperJSONSer = MVCNameAsAttribute deprecated 'Use MVCNameAsAttribute';
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
MVCListOfAttribute = class(TCustomAttribute)
|
2017-02-09 19:33:59 +01:00
|
|
|
private
|
2017-03-01 21:40:57 +01:00
|
|
|
FValue: TClass;
|
2017-03-28 14:52:13 +02:00
|
|
|
protected
|
|
|
|
{ protected declarations }
|
2017-02-09 19:33:59 +01:00
|
|
|
public
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor Create(const AValue: TClass);
|
|
|
|
property Value: TClass read FValue;
|
2017-02-09 19:33:59 +01:00
|
|
|
end;
|
|
|
|
|
2017-04-13 12:46:37 +02:00
|
|
|
MapperListOfAttribute = MVCListOfAttribute deprecated 'Use MVCListOfAttribute';
|
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
MVCDataSetFieldAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
FDataType: TMVCDataType;
|
|
|
|
protected
|
|
|
|
{ protected declarations }
|
|
|
|
public
|
|
|
|
constructor Create(const ADataType: TMVCDataType);
|
|
|
|
property DataType: TMVCDataType read FDataType;
|
|
|
|
end;
|
|
|
|
|
|
|
|
MVCSerializeAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
FSerializationType: TMVCSerializationType;
|
|
|
|
protected
|
|
|
|
{ protected declarations }
|
|
|
|
public
|
|
|
|
constructor Create(const ASerializationType: TMVCSerializationType);
|
|
|
|
property SerializationType: TMVCSerializationType read FSerializationType;
|
|
|
|
end;
|
|
|
|
|
2017-04-24 00:19:53 +02:00
|
|
|
MVCColumnAttribute = class(TCustomAttribute)
|
|
|
|
private
|
|
|
|
FFieldName: string;
|
|
|
|
FIsPK: boolean;
|
|
|
|
procedure SetFieldName(const Value: string);
|
|
|
|
procedure SetIsPK(const Value: boolean);
|
|
|
|
public
|
|
|
|
constructor Create(AFieldName: string; AIsPK: boolean = false);
|
|
|
|
property FieldName: string read FFieldName write SetFieldName;
|
|
|
|
property IsPK: boolean read FIsPK write SetIsPK;
|
|
|
|
end;
|
|
|
|
|
2019-08-13 20:55:51 +02:00
|
|
|
MVCEnumSerializationTypeAttribute = class(TCustomAttribute)
|
2019-08-12 21:48:33 +02:00
|
|
|
private
|
|
|
|
FEnumPrefix: string;
|
|
|
|
FEnumSerializationType: TMVCEnumSerializationType;
|
|
|
|
public
|
|
|
|
constructor Create(const AEnumSerializationType: TMVCEnumSerializationType; const AEnumPrefix: string = '');
|
|
|
|
property EnumSerializationType: TMVCEnumSerializationType read FEnumSerializationType;
|
|
|
|
property EnumPrefix: string read FEnumPrefix;
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
TMVCSerializerHelper = record
|
2017-03-28 14:52:13 +02:00
|
|
|
private
|
|
|
|
{ private declarations }
|
|
|
|
public
|
|
|
|
class function GetKeyName(const AField: TRttiField; const AType: TRttiType): string; overload; static;
|
|
|
|
class function GetKeyName(const AProperty: TRttiProperty; const AType: TRttiType): string; overload; static;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function HasAttribute<T: class>(const AMember: TRttiNamedObject): boolean; overload; static;
|
2019-03-08 09:33:41 +01:00
|
|
|
class function HasAttribute<T: class>(const AMember: TRttiNamedObject; out AAttribute: T): boolean;
|
|
|
|
overload; static;
|
2017-03-28 14:52:13 +02:00
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class function AttributeExists<T: TCustomAttribute>(const AAttributes: TArray<TCustomAttribute>; out AAttribute: T)
|
|
|
|
: boolean; overload; static;
|
|
|
|
class function AttributeExists<T: TCustomAttribute>(const AAttributes: TArray<TCustomAttribute>): boolean;
|
2018-10-31 01:07:23 +01:00
|
|
|
overload; static;
|
2017-03-28 14:52:13 +02:00
|
|
|
|
|
|
|
class procedure EncodeStream(AInput, AOutput: TStream); static;
|
|
|
|
class procedure DecodeStream(AInput, AOutput: TStream); static;
|
|
|
|
|
|
|
|
class function EncodeString(const AInput: string): string; static;
|
|
|
|
class function DecodeString(const AInput: string): string; static;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class procedure DeSerializeStringStream(AStream: TStream; const ASerializedString: string;
|
|
|
|
const AEncoding: string); static;
|
2017-03-28 14:52:13 +02:00
|
|
|
class procedure DeSerializeBase64StringStream(AStream: TStream; const ABase64SerializedString: string); static;
|
|
|
|
|
2017-05-25 12:30:08 +02:00
|
|
|
class function GetTypeKindAsString(const ATypeKind: TTypeKind): string; static;
|
|
|
|
class function StringToTypeKind(const AValue: string): TTypeKind; static;
|
2017-03-28 14:52:13 +02:00
|
|
|
|
|
|
|
class function CreateObject(const AObjectType: TRttiType): TObject; overload; static;
|
|
|
|
class function CreateObject(const AQualifiedClassName: string): TObject; overload; static;
|
2017-05-25 12:30:08 +02:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function IsAPropertyToSkip(const aPropName: string): boolean; static;
|
2017-03-28 14:52:13 +02:00
|
|
|
end;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
TMVCLinksCallback = reference to procedure(const Links: TMVCStringDictionary);
|
|
|
|
|
2019-09-01 20:35:19 +02:00
|
|
|
// Well Known Response Objects
|
|
|
|
[MVCNameCase(ncLowerCase)]
|
|
|
|
TMVCResponseBase = class abstract
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
[MVCNameCase(ncLowerCase)]
|
|
|
|
TMVCTask = class
|
|
|
|
private
|
|
|
|
fID: String;
|
|
|
|
fHREF: String;
|
|
|
|
public
|
|
|
|
property HREF: String read fHREF write fHREF;
|
|
|
|
property ID: String read fID write fID;
|
|
|
|
constructor Create(const HREF, ID: String);
|
|
|
|
end;
|
|
|
|
|
|
|
|
[MVCNameCase(ncLowerCase)]
|
|
|
|
TMVCAcceptedResponse = class(TMVCResponseBase)
|
|
|
|
private
|
|
|
|
fTask: TMVCTask;
|
|
|
|
public
|
|
|
|
property Task: TMVCTask read fTask;
|
2019-09-25 09:14:09 +02:00
|
|
|
// constructor Create(const aTask: TMVCTask); overload;
|
2019-09-01 20:35:19 +02:00
|
|
|
constructor Create(const HREF, ID: String);
|
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
|
2019-09-30 00:05:46 +02:00
|
|
|
[MVCNameCase(ncLowerCase)]
|
|
|
|
TDataObjectHolder = class
|
|
|
|
private
|
|
|
|
FData: TObject;
|
|
|
|
FMetadata: TMVCStringDictionary;
|
|
|
|
FOwns: boolean;
|
|
|
|
FDataSetSerializationType: TMVCDatasetSerializationType;
|
|
|
|
public
|
|
|
|
constructor Create(const AObject: TObject; const AOwns: boolean = false;
|
|
|
|
const ADataSetSerializationType: TMVCDatasetSerializationType = TMVCDatasetSerializationType.
|
|
|
|
dstAllRecords); virtual;
|
|
|
|
destructor Destroy; override;
|
|
|
|
function SerializationType: TMVCDatasetSerializationType;
|
|
|
|
[MVCNameAs('data')]
|
|
|
|
property Items: TObject read FData;
|
|
|
|
[MVCNameAs('meta')]
|
|
|
|
property Metadata: TMVCStringDictionary read FMetadata;
|
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function DateTimeToISOTimeStamp(const ADateTime: TDateTime): string;
|
|
|
|
function DateToISODate(const ADate: TDateTime): string;
|
|
|
|
function TimeToISOTime(const ATime: TTime): string;
|
|
|
|
|
2017-08-29 11:54:22 +02:00
|
|
|
/// <summary>
|
2017-09-23 15:03:07 +02:00
|
|
|
/// Supports ISO8601 in the following formats:
|
|
|
|
/// yyyy-mm-ddThh:nn:ss
|
|
|
|
/// yyyy-mm-ddThh:nn:ss.000Z
|
2017-08-29 11:54:22 +02:00
|
|
|
/// </summary>
|
2017-03-01 21:40:57 +01:00
|
|
|
function ISOTimeStampToDateTime(const ADateTime: string): TDateTime;
|
|
|
|
function ISODateToDate(const ADate: string): TDate;
|
|
|
|
function ISOTimeToTime(const ATime: string): TTime;
|
|
|
|
|
2017-04-13 12:46:37 +02:00
|
|
|
const
|
|
|
|
JSONNameLowerCase = ncLowerCase deprecated 'Use MVCNameCaseAttribute(ncLowerCase)';
|
|
|
|
JSONNameUpperCase = ncUpperCase deprecated 'Use MVCNameCaseAttribute(ncUpperCase)';
|
|
|
|
|
2019-09-30 00:05:46 +02:00
|
|
|
function NewDataObjectHolder(const AObject: TObject; const AMetaFiller: TProc<TMVCStringDictionary> = nil;
|
|
|
|
const AOwns: boolean = false): TDataObjectHolder;
|
|
|
|
function NewCollectionHolder(const AList: TObject; const AMetaFiller: TProc<TMVCStringDictionary> = nil;
|
|
|
|
const AOwns: boolean = false): TDataObjectHolder;
|
|
|
|
|
2017-02-07 14:08:36 +01:00
|
|
|
implementation
|
|
|
|
|
2019-09-30 00:05:46 +02:00
|
|
|
uses
|
|
|
|
MVCFramework.Serializer.JsonDataObjects,
|
|
|
|
MVCFramework.Serializer.Intf;
|
|
|
|
|
|
|
|
function NewDataObjectHolder(const AObject: TObject; const AMetaFiller: TProc<TMVCStringDictionary> = nil;
|
|
|
|
const AOwns: boolean = false): TDataObjectHolder;
|
|
|
|
begin
|
|
|
|
Result := TDataObjectHolder.Create(AObject, AOwns, dstSingleRecord);
|
|
|
|
if Assigned(AMetaFiller) then
|
|
|
|
begin
|
|
|
|
AMetaFiller(Result.FMetadata);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function NewCollectionHolder(const AList: TObject; const AMetaFiller: TProc<TMVCStringDictionary> = nil;
|
|
|
|
const AOwns: boolean = false): TDataObjectHolder;
|
|
|
|
begin
|
|
|
|
Result := TDataObjectHolder.Create(AList, AOwns, dstAllRecords);
|
|
|
|
if Assigned(AMetaFiller) then
|
|
|
|
begin
|
|
|
|
AMetaFiller(Result.FMetadata);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function DateTimeToISOTimeStamp(const ADateTime: TDateTime): string;
|
|
|
|
begin
|
2017-08-29 11:54:22 +02:00
|
|
|
// fs.TimeSeparator := ':';
|
|
|
|
Result := DateToISO8601(ADateTime, true)
|
|
|
|
// Result := FormatDateTime('yyyy-mm-dd hh:nn:ss', ADateTime, fs);
|
2017-03-01 21:40:57 +01:00
|
|
|
end;
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function DateToISODate(const ADate: TDateTime): string;
|
|
|
|
begin
|
|
|
|
Result := FormatDateTime('YYYY-MM-DD', ADate);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TimeToISOTime(const ATime: TTime): string;
|
|
|
|
var
|
|
|
|
fs: TFormatSettings;
|
|
|
|
begin
|
|
|
|
fs.TimeSeparator := ':';
|
|
|
|
Result := FormatDateTime('hh:nn:ss', ATime, fs);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function ISOTimeStampToDateTime(const ADateTime: string): TDateTime;
|
2017-08-29 11:54:22 +02:00
|
|
|
var
|
|
|
|
lDateTime: string;
|
2017-03-01 21:40:57 +01:00
|
|
|
begin
|
2017-08-29 11:54:22 +02:00
|
|
|
lDateTime := ADateTime;
|
|
|
|
if lDateTime.Length < 19 then
|
2019-03-08 09:33:41 +01:00
|
|
|
raise Exception.CreateFmt
|
|
|
|
('Invalid parameter "%s". Hint: DateTime parameters must be formatted in ISO8601 (e.g. 2010-10-12T10:12:23)',
|
2018-10-31 01:07:23 +01:00
|
|
|
[ADateTime]);
|
2017-08-29 11:54:22 +02:00
|
|
|
|
|
|
|
if lDateTime.Chars[10] = ' ' then
|
|
|
|
begin
|
|
|
|
lDateTime := lDateTime.Substring(0, 10) + 'T' + lDateTime.Substring(11);
|
|
|
|
end;
|
|
|
|
Result := ISO8601ToDate(lDateTime, true);
|
2017-03-01 21:40:57 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
function ISODateToDate(const ADate: string): TDate;
|
|
|
|
begin
|
|
|
|
Result := EncodeDate(StrToInt(Copy(ADate, 1, 4)), StrToInt(Copy(ADate, 6, 2)), StrToInt(Copy(ADate, 9, 2)));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function ISOTimeToTime(const ATime: string): TTime;
|
|
|
|
begin
|
|
|
|
Result := EncodeTime(StrToInt(Copy(ATime, 1, 2)), StrToInt(Copy(ATime, 4, 2)), StrToInt(Copy(ATime, 7, 2)), 0);
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{ TMVCSerializerHelper }
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class procedure TMVCSerializerHelper.DeSerializeBase64StringStream(AStream: TStream;
|
|
|
|
const ABase64SerializedString: string);
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
|
|
|
SS: TStringStream;
|
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
AStream.Size := 0;
|
|
|
|
SS := TStringStream.Create(ABase64SerializedString, TEncoding.ASCII);
|
2017-02-07 14:08:36 +01:00
|
|
|
try
|
|
|
|
SS.Position := 0;
|
2017-03-01 21:40:57 +01:00
|
|
|
DecodeStream(SS, AStream);
|
2017-02-07 14:08:36 +01:00
|
|
|
finally
|
|
|
|
SS.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class procedure TMVCSerializerHelper.DeSerializeStringStream(AStream: TStream; const ASerializedString: string;
|
|
|
|
const AEncoding: string);
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Encoding: TEncoding;
|
2017-02-07 14:08:36 +01:00
|
|
|
SS: TStringStream;
|
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
AStream.Position := 0;
|
|
|
|
Encoding := TEncoding.GetEncoding(AEncoding);
|
|
|
|
SS := TStringStream.Create(ASerializedString, Encoding);
|
2017-02-07 14:08:36 +01:00
|
|
|
try
|
|
|
|
SS.Position := 0;
|
2017-03-01 21:40:57 +01:00
|
|
|
AStream.CopyFrom(SS, SS.Size);
|
2017-02-07 14:08:36 +01:00
|
|
|
finally
|
|
|
|
SS.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.GetKeyName(const AField: TRttiField; const AType: TRttiType): string;
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs: TArray<TCustomAttribute>;
|
|
|
|
Attr: TCustomAttribute;
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := AField.Name;
|
|
|
|
|
|
|
|
Attrs := AField.GetAttributes;
|
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is MVCNameAsAttribute then
|
|
|
|
Exit(MVCNameAsAttribute(Attr).Name);
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs := AType.GetAttributes;
|
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is MVCNameCaseAttribute then
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
case MVCNameCaseAttribute(Attr).KeyCase of
|
2017-03-28 14:52:13 +02:00
|
|
|
ncUpperCase:
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Exit(UpperCase(AField.Name));
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
2017-03-28 14:52:13 +02:00
|
|
|
ncLowerCase:
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Exit(LowerCase(AField.Name));
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
2019-08-28 00:18:30 +02:00
|
|
|
ncCamelCase:
|
|
|
|
begin
|
|
|
|
Exit(LowerCase(AField.Name.Chars[0]) + AField.Name.Substring(1));
|
|
|
|
end;
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class function TMVCSerializerHelper.AttributeExists<T>(const AAttributes: TArray<TCustomAttribute>;
|
|
|
|
out AAttribute: T): boolean;
|
2017-02-08 18:29:52 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Att: TCustomAttribute;
|
2017-02-08 18:29:52 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
AAttribute := nil;
|
|
|
|
for Att in AAttributes do
|
|
|
|
if Att is T then
|
2017-02-08 18:29:52 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
AAttribute := T(Att);
|
2017-02-08 18:29:52 +01:00
|
|
|
Break;
|
|
|
|
end;
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := (AAttribute <> nil);
|
|
|
|
end;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class function TMVCSerializerHelper.AttributeExists<T>(const AAttributes: TArray<TCustomAttribute>): boolean;
|
2017-03-01 21:40:57 +01:00
|
|
|
var
|
|
|
|
Att: TCustomAttribute;
|
|
|
|
begin
|
2018-10-31 01:07:23 +01:00
|
|
|
Result := false;
|
2017-03-01 21:40:57 +01:00
|
|
|
for Att in AAttributes do
|
|
|
|
if Att is T then
|
2018-10-31 01:07:23 +01:00
|
|
|
Exit(true);
|
2017-03-01 21:40:57 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.CreateObject(const AObjectType: TRttiType): TObject;
|
2017-03-01 21:40:57 +01:00
|
|
|
var
|
|
|
|
MetaClass: TClass;
|
|
|
|
Method: TRttiMethod;
|
|
|
|
begin
|
|
|
|
MetaClass := nil;
|
|
|
|
Method := nil;
|
|
|
|
|
|
|
|
for Method in AObjectType.GetMethods do
|
|
|
|
if Method.HasExtendedInfo and Method.IsConstructor then
|
|
|
|
if Length(Method.GetParameters) = 0 then
|
|
|
|
begin
|
|
|
|
MetaClass := AObjectType.AsInstance.MetaclassType;
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(MetaClass) then
|
|
|
|
Result := Method.Invoke(MetaClass, []).AsObject
|
|
|
|
else
|
|
|
|
raise EMVCException.CreateFmt('Cannot find a propert constructor for %s', [AObjectType.ToString]);
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.CreateObject(const AQualifiedClassName: string): TObject;
|
2017-03-01 21:40:57 +01:00
|
|
|
var
|
|
|
|
Context: TRttiContext;
|
|
|
|
ObjectType: TRttiType;
|
|
|
|
begin
|
2019-08-05 12:55:44 +02:00
|
|
|
{$IF not Defined(SeattleOrBetter)}
|
2019-08-02 12:32:23 +02:00
|
|
|
Result := nil;
|
2019-08-05 12:55:44 +02:00
|
|
|
{$ENDIF}
|
2017-03-01 21:40:57 +01:00
|
|
|
Context := TRttiContext.Create;
|
|
|
|
try
|
|
|
|
ObjectType := Context.FindType(AQualifiedClassName);
|
|
|
|
if Assigned(ObjectType) then
|
|
|
|
Result := CreateObject(ObjectType)
|
|
|
|
else
|
2019-03-10 16:29:18 +01:00
|
|
|
raise Exception.CreateFmt('Cannot find RTTI for %s. Hint: Is the specified classtype linked in the module?',
|
2019-03-08 09:33:41 +01:00
|
|
|
[AQualifiedClassName]);
|
2017-03-01 21:40:57 +01:00
|
|
|
finally
|
|
|
|
Context.Free;
|
2017-02-08 18:29:52 +01:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class procedure TMVCSerializerHelper.DecodeStream(AInput, AOutput: TStream);
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$IFDEF SYSTEMNETENCODING}
|
2017-03-01 21:40:57 +01:00
|
|
|
TNetEncoding.Base64.Decode(AInput, AOutput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ELSE}
|
2017-03-01 21:40:57 +01:00
|
|
|
Soap.EncdDecd.DecodeStream(AInput, AOutput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ENDIF}
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.DecodeString(const AInput: string): string;
|
2017-02-10 14:19:55 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$IFDEF SYSTEMNETENCODING}
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := TNetEncoding.Base64.Decode(AInput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ELSE}
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := Soap.EncdDecd.DecodeString(AInput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ENDIF}
|
2017-02-10 14:19:55 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class procedure TMVCSerializerHelper.EncodeStream(AInput, AOutput: TStream);
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$IFDEF SYSTEMNETENCODING}
|
2017-03-01 21:40:57 +01:00
|
|
|
TNetEncoding.Base64.Encode(AInput, AOutput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ELSE}
|
2017-03-01 21:40:57 +01:00
|
|
|
Soap.EncdDecd.EncodeStream(AInput, AOutput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ENDIF}
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.EncodeString(const AInput: string): string;
|
2017-02-10 14:19:55 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$IFDEF SYSTEMNETENCODING}
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := TNetEncoding.Base64.Encode(AInput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ELSE}
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := Soap.EncdDecd.EncodeString(AInput);
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
{$ENDIF}
|
2017-02-10 14:19:55 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.GetKeyName(const AProperty: TRttiProperty; const AType: TRttiType): string;
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs: TArray<TCustomAttribute>;
|
|
|
|
Attr: TCustomAttribute;
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := AProperty.Name;
|
|
|
|
|
|
|
|
Attrs := AProperty.GetAttributes;
|
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is MVCNameAsAttribute then
|
|
|
|
Exit(MVCNameAsAttribute(Attr).Name);
|
2017-02-07 14:08:36 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs := AType.GetAttributes;
|
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is MVCNameCaseAttribute then
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
case MVCNameCaseAttribute(Attr).KeyCase of
|
2017-03-28 14:52:13 +02:00
|
|
|
ncUpperCase:
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Exit(UpperCase(AProperty.Name));
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
2017-03-28 14:52:13 +02:00
|
|
|
ncLowerCase:
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Exit(LowerCase(AProperty.Name));
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
2019-10-09 23:44:44 +02:00
|
|
|
ncCamelCase:
|
|
|
|
begin
|
|
|
|
Exit(LowerCase(AProperty.Name.Chars[0]) + AProperty.Name.Substring(1));
|
|
|
|
end;
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.GetTypeKindAsString(const ATypeKind: TTypeKind): string;
|
2017-02-09 11:24:18 +01:00
|
|
|
begin
|
|
|
|
Result := GetEnumName(TypeInfo(TTypeKind), Ord(ATypeKind));
|
|
|
|
Result := Result.Remove(0, 2).ToLower;
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.HasAttribute<T>(const AMember: TRttiNamedObject): boolean;
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs: TArray<TCustomAttribute>;
|
|
|
|
Attr: TCustomAttribute;
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2018-10-31 01:07:23 +01:00
|
|
|
Result := false;
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs := AMember.GetAttributes;
|
|
|
|
if Length(Attrs) = 0 then
|
2018-10-31 01:07:23 +01:00
|
|
|
Exit(false);
|
2017-03-01 21:40:57 +01:00
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is T then
|
2018-10-31 01:07:23 +01:00
|
|
|
Exit(true);
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.HasAttribute<T>(const AMember: TRttiNamedObject; out AAttribute: T): boolean;
|
2017-02-07 14:08:36 +01:00
|
|
|
var
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs: TArray<TCustomAttribute>;
|
|
|
|
Attr: TCustomAttribute;
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
|
|
|
AAttribute := nil;
|
2018-10-31 01:07:23 +01:00
|
|
|
Result := false;
|
2017-03-01 21:40:57 +01:00
|
|
|
Attrs := AMember.GetAttributes;
|
|
|
|
for Attr in Attrs do
|
|
|
|
if Attr is T then
|
2017-02-07 14:08:36 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
AAttribute := T(Attr);
|
2018-10-31 01:07:23 +01:00
|
|
|
Exit(true);
|
2017-02-07 14:08:36 +01:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-03-08 09:33:41 +01:00
|
|
|
class function TMVCSerializerHelper.IsAPropertyToSkip(const aPropName: string): boolean;
|
2017-05-25 12:30:08 +02:00
|
|
|
begin
|
|
|
|
Result := (aPropName = 'RefCount') or (aPropName = 'Disposed');
|
|
|
|
end;
|
|
|
|
|
2018-10-31 01:07:23 +01:00
|
|
|
class function TMVCSerializerHelper.StringToTypeKind(const AValue: string): TTypeKind;
|
2017-02-09 11:24:18 +01:00
|
|
|
begin
|
|
|
|
Result := TTypeKind(GetEnumValue(TypeInfo(TTypeKind), 'tk' + AValue));
|
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
{ MVCValueAsTypeAttribute }
|
2017-02-08 11:42:05 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor MVCValueAsTypeAttribute.Create(AValueTypeInfo: PTypeInfo);
|
2017-02-08 11:42:05 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
inherited Create;
|
|
|
|
FValueTypeInfo := AValueTypeInfo;
|
2017-02-08 11:42:05 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function MVCValueAsTypeAttribute.ValueTypeInfo: PTypeInfo;
|
2017-02-08 11:42:05 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := FValueTypeInfo;
|
2017-02-09 19:33:59 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
{ MVCNameCaseAttribute }
|
2017-02-09 19:33:59 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor MVCNameCaseAttribute.Create(const AKeyCase: TMVCNameCase);
|
2017-02-09 19:33:59 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
inherited Create;
|
|
|
|
FKeyCase := AKeyCase;
|
2017-02-09 19:33:59 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function MVCNameCaseAttribute.GetKeyCase: TMVCNameCase;
|
2017-02-09 19:33:59 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := FKeyCase;
|
2017-02-08 11:42:05 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
{ MVCNameAsAttribute }
|
2017-02-09 11:24:18 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor MVCNameAsAttribute.Create(const AName: string);
|
2017-02-09 11:24:18 +01:00
|
|
|
begin
|
|
|
|
inherited Create;
|
2017-03-01 21:40:57 +01:00
|
|
|
FName := AName;
|
2017-02-09 11:24:18 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
function MVCNameAsAttribute.GetName: string;
|
2017-02-09 11:24:18 +01:00
|
|
|
begin
|
2017-03-01 21:40:57 +01:00
|
|
|
Result := FName;
|
2017-02-09 11:24:18 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
{ MVCListOfAttribute }
|
2017-02-09 19:33:59 +01:00
|
|
|
|
2017-03-01 21:40:57 +01:00
|
|
|
constructor MVCListOfAttribute.Create(const AValue: TClass);
|
2017-02-09 19:33:59 +01:00
|
|
|
begin
|
|
|
|
inherited Create;
|
2017-03-01 21:40:57 +01:00
|
|
|
FValue := AValue;
|
2017-02-09 19:33:59 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
{ MVCDataSetFieldAttribute }
|
2017-03-02 12:57:40 +01:00
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
constructor MVCDataSetFieldAttribute.Create(const ADataType: TMVCDataType);
|
2017-03-02 12:57:40 +01:00
|
|
|
begin
|
|
|
|
inherited Create;
|
2017-03-28 14:52:13 +02:00
|
|
|
FDataType := ADataType;
|
2017-03-02 12:57:40 +01:00
|
|
|
end;
|
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
{ MVCSerializeAttribute }
|
2017-03-02 12:57:40 +01:00
|
|
|
|
2017-03-28 14:52:13 +02:00
|
|
|
constructor MVCSerializeAttribute.Create(const ASerializationType: TMVCSerializationType);
|
2017-03-02 12:57:40 +01:00
|
|
|
begin
|
2017-03-28 14:52:13 +02:00
|
|
|
inherited Create;
|
|
|
|
FSerializationType := ASerializationType;
|
2017-03-02 12:57:40 +01:00
|
|
|
end;
|
|
|
|
|
2017-04-24 00:19:53 +02:00
|
|
|
{ MVCColumnAttribute }
|
|
|
|
|
|
|
|
constructor MVCColumnAttribute.Create(AFieldName: string; AIsPK: boolean);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FFieldName := AFieldName;
|
|
|
|
FIsPK := AIsPK;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure MVCColumnAttribute.SetFieldName(const Value: string);
|
|
|
|
begin
|
|
|
|
FFieldName := Value;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure MVCColumnAttribute.SetIsPK(const Value: boolean);
|
|
|
|
begin
|
|
|
|
FIsPK := Value;
|
|
|
|
end;
|
|
|
|
|
2019-08-13 20:55:51 +02:00
|
|
|
{ MVCEnumSerializationTypeAttribute }
|
2017-09-28 00:14:34 +02:00
|
|
|
|
2019-08-13 20:55:51 +02:00
|
|
|
constructor MVCEnumSerializationTypeAttribute.Create(const AEnumSerializationType: TMVCEnumSerializationType;
|
2019-08-12 21:48:33 +02:00
|
|
|
const AEnumPrefix: string);
|
|
|
|
begin
|
|
|
|
FEnumSerializationType := AEnumSerializationType;
|
|
|
|
FEnumPrefix := AEnumPrefix;
|
|
|
|
end;
|
2017-09-28 00:14:34 +02:00
|
|
|
|
2019-09-01 20:35:19 +02:00
|
|
|
{ TMVCTask }
|
|
|
|
|
|
|
|
constructor TMVCTask.Create(const HREF, ID: String);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
fHREF := HREF;
|
|
|
|
fID := ID;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TMVCAcceptedResponse }
|
|
|
|
|
2019-09-25 09:14:09 +02:00
|
|
|
// constructor TMVCAcceptedResponse.Create(const aTask: TMVCTask);
|
|
|
|
// begin
|
|
|
|
// inherited Create;
|
|
|
|
// fTask := aTask;
|
|
|
|
// end;
|
2019-09-01 20:35:19 +02:00
|
|
|
|
|
|
|
constructor TMVCAcceptedResponse.Create(const HREF, ID: String);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
fTask := TMVCTask.Create(HREF, ID);
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMVCAcceptedResponse.Destroy;
|
|
|
|
begin
|
|
|
|
fTask.Free;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2019-09-30 00:05:46 +02:00
|
|
|
{ TDataObjectHolder }
|
|
|
|
|
|
|
|
constructor TDataObjectHolder.Create(const AObject: TObject; const AOwns: boolean;
|
|
|
|
const ADataSetSerializationType: TMVCDatasetSerializationType);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FData := AObject;
|
|
|
|
FMetadata := TMVCStringDictionary.Create;
|
|
|
|
FOwns := AOwns;
|
|
|
|
FDataSetSerializationType := ADataSetSerializationType;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TDataObjectHolder.Destroy;
|
|
|
|
begin
|
|
|
|
FMetadata.Free;
|
|
|
|
if FOwns then
|
|
|
|
begin
|
|
|
|
FData.Free;
|
|
|
|
end;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TDataObjectHolder.SerializationType: TMVCDatasetSerializationType;
|
|
|
|
begin
|
2019-10-09 23:14:56 +02:00
|
|
|
Result := FDataSetSerializationType;
|
2019-09-30 00:05:46 +02:00
|
|
|
end;
|
|
|
|
|
2017-02-07 14:08:36 +01:00
|
|
|
end.
|