InstantClasses
Unit: InstantClassesCategory: Core
Overview
The InstantClasses unit provides fundamental infrastructure classes for InstantObjects. These base classes handle exceptions, streaming, serialization, collections, and XML support used throughout the framework.
Key Components:
- Exception System - Hierarchical exception classes
- Streaming - Binary and XML serialization
- Collections - Extended collection classes with naming
- Readers/Writers - Low-level stream reading/writing
- Converters - Binary ↔ XML conversion
- Abstract Bases - Base classes for objects and attributes
- Utilities - Helper functions and classes
Exception Hierarchy
EInstantError
Base exception class for all InstantObjects exceptions.
Inheritance: Exception → EInstantError
Key Features
- Wraps original exceptions
- Resource string support
- Formatted messages
- Exception chaining
Properties
| Property | Type | Description |
|---|---|---|
OriginalException | TObject | Wrapped original exception (if any) |
Constructors
constructor Create(const Msg: string; E: TObject = nil);
constructor CreateFmt(const Msg: string; const Args: array of const; E: TObject = nil);
constructor CreateRes(ResStringRec: PResStringRec; E: TObject = nil);
constructor CreateResFmt(ResStringRec: PResStringRec; const Args: array of const; E: TObject = nil);Example Usage
// Simple message
raise EInstantError.Create('Object not found');
// Formatted message
raise EInstantError.CreateFmt('Object %s not found', [ObjectId]);
// Wrap exception
try
// Database operation
except
on E: EDatabaseError do
raise EInstantError.Create('Database operation failed', E);
end;
// Resource string
raise EInstantError.CreateRes(@SInstantObjectNotFound);
// Formatted resource string
raise EInstantError.CreateResFmt(@SInstantInvalidValue, [FieldName, Value]);Exception Handling
try
Contact.Store;
except
on E: EInstantError do
begin
ShowMessage('InstantObjects error: ' + E.Message);
// Check for original exception
if Assigned(E.OriginalException) then
if E.OriginalException is EDatabaseError then
ShowMessage('Database error: ' + EDatabaseError(E.OriginalException).Message);
end;
end;Specialized Exception Classes
EInstantStreamError = class(EInstantError) // Stream operations
EInstantValidationError = class(EInstantError) // Validation failures
EInstantRangeError = class(EInstantError) // Value out of range
EInstantConversionError = class(EInstantError) // Type conversion errorsUsage:
// Validation error
if not IsValidEmail(Email) then
raise EInstantValidationError.CreateFmt('Invalid email: %s', [Email]);
// Range error
if Age < 0 then
raise EInstantRangeError.CreateFmt('Age must be >= 0, got %d', [Age]);
// Conversion error
try
IntValue := StrToInt(StringValue);
except
on E: EConvertError do
raise EInstantConversionError.Create('Cannot convert to integer', E);
end;TInstantStreamable
Base class for objects that can be serialized to/from streams.
Inheritance: TPersistent → TInstantStreamable
Key Methods
// Streaming
procedure LoadFromStream(Stream: TStream; ProcessEvent: TInstantProcessObjectEvent = nil);
procedure SaveToStream(Stream: TStream; ProcessEvent: TInstantProcessObjectEvent = nil);
// Assign from another instance
procedure Assign(Source: TPersistent); override;Protected Methods
// Override in descendants for custom serialization
procedure ReadObject(Reader: TInstantReader); virtual;
procedure WriteObject(Writer: TInstantWriter); virtual;
// Conversion support
class procedure ConvertToBinary(Converter: TInstantTextToBinaryConverter); virtual;
class procedure ConvertToText(Converter: TInstantBinaryToTextConverter); virtual;
// Factory method
class function CreateInstance(Arg: Pointer = nil): TInstantStreamable; virtual;Example Usage
type
TMyData = class(TInstantStreamable)
private
FName: string;
FValue: Integer;
protected
procedure ReadObject(Reader: TInstantReader); override;
procedure WriteObject(Writer: TInstantWriter); override;
end;
procedure TMyData.ReadObject(Reader: TInstantReader);
begin
inherited;
FName := Reader.ReadString;
FValue := Reader.ReadInteger;
end;
procedure TMyData.WriteObject(Writer: TInstantWriter);
begin
inherited;
Writer.WriteString(FName);
Writer.WriteInteger(FValue);
end;
// Usage
var
Data: TMyData;
Stream: TFileStream;
begin
Data := TMyData.Create;
try
Data.FName := 'Test';
Data.FValue := 42;
Stream := TFileStream.Create('data.bin', fmCreate);
try
Data.SaveToStream(Stream);
finally
Stream.Free;
end;
finally
Data.Free;
end;
end;Collection Classes
TInstantCollectionItem
Enhanced TCollectionItem with name support.
Inheritance: TCollectionItem → TInstantCollectionItem
Key Properties
| Property | Type | Description |
|---|---|---|
Name | string | Item name |
DisplayName | string | Display name (defaults to Name) |
Key Methods
procedure Assign(Source: TPersistent); override;
// Streaming support
procedure ReadObject(Reader: TInstantReader); virtual;
procedure WriteObject(Writer: TInstantWriter); virtual;
// Factory
class function CreateInstance(Arg: Pointer = nil): TInstantCollectionItem; virtual;Example
type
TMyItem = class(TInstantCollectionItem)
private
FValue: Integer;
published
property Value: Integer read FValue write FValue;
end;
var
Item: TMyItem;
begin
Item := TMyItem(Collection.Add);
Item.Name := 'Item1';
Item.Value := 100;
end;TInstantCollection
Enhanced TCollection with name-based access.
Inheritance: TCollection → TInstantCollection
Key Methods
constructor Create(ItemClass: TInstantCollectionItemClass);
// Name-based access
function Find(const AName: string): TInstantCollectionItem;
function IndexOf(const AName: string): Integer; overload;
function IndexOf(Item: TInstantCollectionItem): Integer; overload;
function Remove(Item: TInstantCollectionItem): Integer;
// Utilities
procedure GetItemNames(List: TStrings);
// Streaming
procedure ReadObject(Reader: TInstantReader); virtual;
procedure WriteObject(Writer: TInstantWriter); virtual;
// Factory
class function CreateInstance(Arg: Pointer = nil): TInstantCollection; virtual;Example Usage
var
Collection: TInstantCollection;
Item: TInstantCollectionItem;
Names: TStringList;
begin
Collection := TInstantCollection.Create(TMyItem);
try
// Add items
Item := Collection.Add;
Item.Name := 'First';
Item := Collection.Add;
Item.Name := 'Second';
// Find by name
Item := Collection.Find('First');
if Assigned(Item) then
ShowMessage('Found: ' + Item.Name);
// Get all names
Names := TStringList.Create;
try
Collection.GetItemNames(Names);
ShowMessage(Names.CommaText);
finally
Names.Free;
end;
// Remove by name
Item := Collection.Find('Second');
if Assigned(Item) then
Collection.Remove(Item);
finally
Collection.Free;
end;
end;TInstantOwnedCollection
Collection with owner reference.
Inheritance: TInstantCollection → TInstantOwnedCollection
Key Properties
| Property | Type | Description |
|---|---|---|
Owner | TPersistent | Collection owner |
Constructor
constructor Create(AOwner: TPersistent; ItemClass: TInstantCollectionItemClass);Example
type
TMyObject = class(TPersistent)
private
FItems: TInstantOwnedCollection;
public
constructor Create;
destructor Destroy; override;
property Items: TInstantOwnedCollection read FItems;
end;
constructor TMyObject.Create;
begin
inherited;
FItems := TInstantOwnedCollection.Create(Self, TMyItem);
end;
destructor TMyObject.Destroy;
begin
FItems.Free;
inherited;
end;
// Usage
var
MyObj: TMyObject;
begin
MyObj := TMyObject.Create;
try
ShowMessage('Owner: ' + MyObj.Items.Owner.ClassName); // TMyObject
finally
MyObj.Free;
end;
end;Reader and Writer Classes
TInstantReader
Low-level stream reader for object serialization.
Inheritance: TAbstractReader → TInstantReader
Key Methods
constructor Create(Stream: TStream; BufSize: Integer = InstantBufferSize);
// Read operations
function ReadObject(AObject: TPersistent = nil; Arg: Pointer = nil): TPersistent; virtual;
procedure ReadProperties(AObject: TPersistent);
procedure ReadBinary(ReadData: TStreamProc);
procedure SkipValue;Properties
| Property | Type | Description |
|---|---|---|
Stream | TStream | Underlying stream |
Example
var
Reader: TInstantReader;
Stream: TFileStream;
Obj: TMyObject;
begin
Stream := TFileStream.Create('object.bin', fmOpenRead);
try
Reader := TInstantReader.Create(Stream);
try
Obj := Reader.ReadObject as TMyObject;
try
// Use object
finally
Obj.Free;
end;
finally
Reader.Free;
end;
finally
Stream.Free;
end;
end;TInstantWriter
Low-level stream writer for object serialization.
Inheritance: TAbstractWriter → TInstantWriter
Key Methods
constructor Create(Stream: TStream; BufSize: Integer = InstantBufferSize);
// Write operations
procedure WriteObject(AObject: TPersistent); virtual;
procedure WriteProperties(AObject: TPersistent);
procedure WriteBinary(WriteData: TStreamProc);
procedure WriteValue(Value: TValueType);Properties
| Property | Type | Description |
|---|---|---|
Stream | TStream | Underlying stream |
Example
var
Writer: TInstantWriter;
Stream: TFileStream;
Obj: TMyObject;
begin
Obj := TMyObject.Create;
try
Stream := TFileStream.Create('object.bin', fmCreate);
try
Writer := TInstantWriter.Create(Stream);
try
Writer.WriteObject(Obj);
finally
Writer.Free;
end;
finally
Stream.Free;
end;
finally
Obj.Free;
end;
end;Stream Classes
TInstantStream
Enhanced stream with object serialization support.
Inheritance: TStream → TInstantStream
Key Properties
| Property | Type | Description |
|---|---|---|
Source | TStream | Underlying stream |
FreeSource | Boolean | Free source on destroy |
OnProcessObject | TInstantProcessObjectEvent | Object processing callback |
Key Methods
constructor Create(ASource: TStream = nil; AFreeSource: Boolean = False);
// Object operations
function ReadObject(AObject: TPersistent = nil; Arg: Pointer = nil): TPersistent;
procedure WriteObject(AObject: TPersistent);
// Resource operations
function ReadObjectRes(AObject: TPersistent = nil; Arg: Pointer = nil): TPersistent;
procedure WriteObjectRes(const ResName: string; AObject: TPersistent);
// Alignment
procedure AlignStream;Example
var
InstStream: TInstantStream;
FileStream: TFileStream;
Obj: TMyObject;
begin
FileStream := TFileStream.Create('data.dat', fmOpenRead);
try
InstStream := TInstantStream.Create(FileStream, True); // Will free FileStream
try
Obj := InstStream.ReadObject as TMyObject;
try
// Use object
finally
Obj.Free;
end;
finally
InstStream.Free; // Also frees FileStream
end;
except
FileStream.Free; // Only if InstantStream creation failed
raise;
end;
end;TInstantResourceStream
Stream for reading Windows resources.
Inheritance: TInstantStream → TInstantResourceStream
Constructors
constructor Create(Instance: THandle; const ResName: string; ResType: PChar);
constructor CreateFromId(Instance: THandle; ResID: Integer; ResType: PChar);Example
var
ResStream: TInstantResourceStream;
Model: TInstantModel;
begin
ResStream := TInstantResourceStream.Create(HInstance, 'MODEL', RT_RCDATA);
try
Model := ResStream.ReadObject as TInstantModel;
try
// Use model
finally
Model.Free;
end;
finally
ResStream.Free;
end;
end;TInstantFileStream
Simplified file stream with object support.
Inheritance: TInstantStream → TInstantFileStream
Constructor
constructor Create(const FileName: string; Mode: Word);Example
var
FileStream: TInstantFileStream;
Obj: TMyObject;
begin
FileStream := TInstantFileStream.Create('data.dat', fmOpenRead);
try
Obj := FileStream.ReadObject as TMyObject;
try
// Use object
finally
Obj.Free;
end;
finally
FileStream.Free;
end;
end;XML Support Classes
TInstantXMLProducer
Generates XML from binary stream.
Inheritance: TObject → TInstantXMLProducer
Key Properties
| Property | Type | Description |
|---|---|---|
Stream | TStream | Output XML stream |
CurrentTag | string | Current open tag |
Eof | Boolean | End of output reached |
Position | Integer | Current stream position |
Key Methods
// Tag operations
procedure WriteStartTag(const TagName: string);
procedure WriteEndTag;
procedure WriteAnyTag(const TagName: string);
// Data operations
procedure WriteData(const Data: string);TInstantXMLProcessor
Parses XML into binary stream.
Inheritance: TObject → TInstantXMLProcessor
Key Properties
| Property | Type | Description |
|---|---|---|
Stream | TStream | Input XML stream |
CurrentTag | string | Current tag being processed |
Token | TInstantXMLToken | Current token type |
Key Methods
// Token reading
function ReadToken: TInstantXMLToken;
procedure MatchToken(AToken: TInstantXMLToken);
function MatchText(const AText: string): Boolean;
// Tag matching
function MatchStartTag(const TagName: string): Boolean;
function MatchEndTag: Boolean;
procedure MatchAnyTag;Token Types
type
TInstantXMLToken = (
xtNone, // No token
xtStartTag, // <Tag>
xtEndTag, // </Tag>
xtAnyTag, // <Tag/>
xtData // Text content
);Converter Classes
TInstantBinaryToTextConverter
Converts binary stream to XML.
Inheritance: TInstantConverter → TInstantBinaryToTextConverter
Constructor
constructor Create(Input, Output: TStream);Key Methods
procedure Convert;
procedure ConvertProperties;Example
var
BinaryStream, XMLStream: TStream;
Converter: TInstantBinaryToTextConverter;
begin
BinaryStream := TFileStream.Create('data.bin', fmOpenRead);
try
XMLStream := TFileStream.Create('data.xml', fmCreate);
try
Converter := TInstantBinaryToTextConverter.Create(BinaryStream, XMLStream);
try
Converter.Convert;
finally
Converter.Free;
end;
finally
XMLStream.Free;
end;
finally
BinaryStream.Free;
end;
end;TInstantTextToBinaryConverter
Converts XML to binary stream.
Inheritance: TInstantConverter → TInstantTextToBinaryConverter
Constructor
constructor Create(Input, Output: TStream);Key Methods
procedure Convert;
procedure ConvertProperties;
procedure ConvertProperties(const StopTag: string); overload;Example
var
XMLStream, BinaryStream: TStream;
Converter: TInstantTextToBinaryConverter;
begin
XMLStream := TFileStream.Create('data.xml', fmOpenRead);
try
BinaryStream := TFileStream.Create('data.bin', fmCreate);
try
Converter := TInstantTextToBinaryConverter.Create(XMLStream, BinaryStream);
try
Converter.Convert;
finally
Converter.Free;
end;
finally
BinaryStream.Free;
end;
finally
XMLStream.Free;
end;
end;Abstract Base Classes
TInstantAbstractObject
Abstract base for persistent objects (parent of TInstantObject).
Inheritance: TInstantStreamable → TInstantAbstractObject
Key Properties
| Property | Type | Description |
|---|---|---|
Connector | TComponent | Associated connector |
Abstract Methods
constructor Retrieve(const AObjectId: string; CreateIfMissing: Boolean = False;
Refresh: Boolean = False; AConnector: TComponent = nil;
const AObjectData: TInstantAbstractObjectData = nil); virtual; abstract;TInstantAbstractAttribute
Abstract base for attributes.
Inheritance: TInstantStreamable → TInstantAbstractAttribute
Key Properties
| Property | Type | Description |
|---|---|---|
Owner | TInstantAbstractObject | Owning object |
Metadata | TInstantCollectionItem | Attribute metadata |
Constructor
constructor Create(AOwner: TInstantAbstractObject; AMetadata: TInstantCollectionItem); virtual;Abstract Methods
procedure Initialize; virtual; abstract;Stream Format Enumeration
TInstantStreamFormat
Defines serialization formats.
type
TInstantStreamFormat = (
sfBinary, // Binary format (default)
sfXML, // XML text format
sfJSON // JSON format (if DELPHI_NEON defined)
);Format Descriptions:
const
AInstantStreamFormatStr: array[TInstantStreamFormat] of string = (
'Binary format',
'XML format'
{$IFDEF DELPHI_NEON}
, 'JSON format'
{$ENDIF}
);Utility Functions
Object Streaming Functions
// Read object from stream
function InstantReadObject(Stream: TStream; Format: TInstantStreamFormat;
AObject: TPersistent = nil): TPersistent;
function InstantReadObjectFromStream(Stream: TStream;
AObject: TPersistent = nil;
ProcessEvent: TInstantProcessObjectEvent = nil;
Arg: Pointer = nil): TPersistent;
// Write object to stream
procedure InstantWriteObject(Stream: TStream; Format: TInstantStreamFormat;
AObject: TPersistent);
procedure InstantWriteObjectToStream(Stream: TStream; AObject: TPersistent;
ProcessEvent: TInstantProcessObjectEvent = nil);Multiple Objects
// Read multiple objects
procedure InstantReadObjects(Stream: TStream; Format: TInstantStreamFormat;
Objects: TList);
// Write multiple objects
procedure InstantWriteObjects(Stream: TStream; Format: TInstantStreamFormat;
Objects: TList);Conversion Functions
// Convert between binary and XML
procedure InstantObjectBinaryToText(Input, Output: TStream);
procedure InstantObjectTextToBinary(Input, Output: TStream);XML Tag Functions
// Build XML tags
function InstantBuildStartTag(const TagName: string): string;
function InstantBuildEndTag(const TagName: string): string;Class Checking
// Verify class inheritance
procedure InstantCheckClass(AClass: TClass; MinimumClass: TClass);Usage Examples
Save/Load with Different Formats
procedure SaveObject(Obj: TPersistent; const FileName: string;
Format: TInstantStreamFormat);
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
InstantWriteObject(Stream, Format, Obj);
finally
Stream.Free;
end;
end;
function LoadObject(const FileName: string;
Format: TInstantStreamFormat): TPersistent;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
Result := InstantReadObject(Stream, Format);
finally
Stream.Free;
end;
end;
// Usage
var
Contact: TContact;
begin
Contact := TContact.Create;
try
Contact.Name := 'John Doe';
// Save as binary
SaveObject(Contact, 'contact.bin', sfBinary);
// Save as XML
SaveObject(Contact, 'contact.xml', sfXML);
{$IFDEF DELPHI_NEON}
// Save as JSON
SaveObject(Contact, 'contact.json', sfJSON);
{$ENDIF}
finally
Contact.Free;
end;
// Load
Contact := LoadObject('contact.xml', sfXML) as TContact;
try
ShowMessage(Contact.Name);
finally
Contact.Free;
end;
end;Convert Binary to XML
procedure ConvertBinaryFileToXML(const BinaryFile, XMLFile: string);
var
BinStream, XMLStream: TStream;
begin
BinStream := TFileStream.Create(BinaryFile, fmOpenRead);
try
XMLStream := TFileStream.Create(XMLFile, fmCreate);
try
InstantObjectBinaryToText(BinStream, XMLStream);
finally
XMLStream.Free;
end;
finally
BinStream.Free;
end;
end;
// Usage
ConvertBinaryFileToXML('model.bin', 'model.xml');Save Multiple Objects
procedure SaveMultipleObjects(Objects: TObjectList; const FileName: string);
var
Stream: TFileStream;
List: TList;
I: Integer;
begin
List := TList.Create;
try
for I := 0 to Objects.Count - 1 do
List.Add(Objects[I]);
Stream := TFileStream.Create(FileName, fmCreate);
try
InstantWriteObjects(Stream, sfXML, List);
finally
Stream.Free;
end;
finally
List.Free;
end;
end;
procedure LoadMultipleObjects(const FileName: string; Objects: TObjectList);
var
Stream: TFileStream;
List: TList;
I: Integer;
begin
List := TList.Create;
try
Stream := TFileStream.Create(FileName, fmOpenRead);
try
InstantReadObjects(Stream, sfXML, List);
finally
Stream.Free;
end;
Objects.Clear;
for I := 0 to List.Count - 1 do
Objects.Add(List[I]);
finally
List.Free;
end;
end;Custom Exception with Original
procedure SafeDatabaseOperation;
begin
try
// Database operation that might fail
Connector.Broker.Execute('INVALID SQL');
except
on E: EDatabaseError do
begin
// Wrap with InstantObjects exception
raise EInstantError.CreateFmt(
'Database operation failed: %s', [E.Message], E);
end;
end;
end;
// Catch and analyze
try
SafeDatabaseOperation;
except
on E: EInstantError do
begin
ShowMessage('Error: ' + E.Message);
if Assigned(E.OriginalException) and
(E.OriginalException is EDatabaseError) then
begin
ShowMessage('Original DB Error: ' +
EDatabaseError(E.OriginalException).Message);
end;
end;
end;Best Practices
Exception Handling
- Always catch specific exception types
- Wrap external exceptions in EInstantError
- Preserve original exception for debugging
- Use resource strings for messages
Streaming
- Use appropriate format (sfBinary for speed, sfXML for debugging)
- Always free streams in try-finally
- Consider
FreeSourcefor nested streams - Use process events for progress feedback
Collections
- Use named access for clarity
- Prefer TInstantOwnedCollection for ownership
- Call GetItemNames for UI population
XML Conversion
- Convert to XML for version control
- Keep binary for runtime performance
- Use converters for migration
Custom Streamable Classes
- Override ReadObject/WriteObject
- Call inherited first
- Handle versioning explicitly
- Test round-trip serialization
See Also
- InstantPersistence - Uses these base classes
- InstantMetadata - Uses collections
- InstantTypes - Type definitions
- Creating Objects - Object creation and persistence
Version History
- Version 3.0 - Initial infrastructure
- Version 3.5 - XML support added
- Version 4.0 - Enhanced exception system
- Version 4.2 - 64-bit support
- Version 4.3 - JSON format support (with Neon)
