Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#19

AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen

  Alt 31. Okt 2014, 13:11
Ich würde dir empfehlen eine abstrakte Klasse zu bauen, wo die konkreten Ableitungen jeweils die alten und neuen Varianten kapseln.
Bei geschickter Implementierung kannst du mit FooNew.Assign( FooOld ); deine Daten konvertieren und auch in Zukunft noch die alten Daten lesen und (prinzipiell) sogar noch schreiben.

Delphi-Quellcode:
// Der abstrakte Teil, der auch immer wieder erweitert wird, und den aktuellen Stand repräsentiert
unit Settings;

interface

uses
  System.Classes;

type
  TSettings = class abstract( TPersistent )
  private
    procedure AssignToSettings( Dest: TSettings );
  protected
    // der Getter kann hier auch virtuell implementiert werden
    // damit bei neuen Eigenschaften wenigstens ein Default-Wert
    // übermittelt wird, wenn der in den alten Informationen
    // gar nicht verfügbar oder ableitbar ist
    function GetBaud: Byte; virtual; abstract;
    procedure SetBaud( const Value: Byte ); virtual; abstract;
    procedure AssignTo( Dest: TPersistent ); override;
  public
    property Baud: Byte read GetBaud write SetBaud;
  end;

implementation

{ TSettings }

procedure TSettings.AssignTo( Dest: TPersistent );
begin
  if Dest is TSettings
  then
    AssignToSettings( Dest as TSettings )
  else
    inherited;
end;

procedure TSettings.AssignToSettings( Dest: TSettings );
begin
  Dest.SetBaud( Self.GetBaud );
end;

end.
Implementierung eines alten Daten-Records
Delphi-Quellcode:
unit Settings.v1_0;

interface

uses
  Settings;

type
  T_Settings_XE4 = Packed Record
    ID: Byte;
    Baud: Byte;
    Line: Byte;
    TSN1: Byte;
    TSN2: Byte;
    TSN3: Byte;
    TSN4: Byte;
    TSN5: Byte;
    TSN6: Byte;
    Description: ShortString;
    ConnectionDef: ShortString;
  end;

  TSettings_V1_0 = class( TSettings )
  private
    FData: T_Settings_XE4;
  protected
    function GetBaud: Byte; override;
    procedure SetBaud( const Value: Byte ); override;
  public
    constructor Create( Data: T_Settings_XE4 );
  end;

implementation

{ TSettings_V1_0 }

constructor TSettings_V1_0.Create( Data: T_Settings_XE4 );
begin
  inherited Create;
  FData := Data;
end;

function TSettings_V1_0.GetBaud: Byte;
begin
  Result := FData.Baud;
end;

procedure TSettings_V1_0.SetBaud( const Value: Byte );
begin
  FData.Baud := Value;
end;

end.
Implementierung eines neuen Daten-Objekts
Delphi-Quellcode:
unit Settings.v2_0;

interface

uses
  Settings;

type
  T_Settings_Data = class
  private
    FBaud: Integer;
  public
    property Baud: Integer read FBaud write FBaud;
  end;

  TSettings_v2_0 = class( TSettings )
  private
    FData: T_Settings_Data;
    FOwnsObject: Boolean;
  protected
    function GetBaud: Byte; override;
    procedure SetBaud( const Value: Byte ); override;
  public
    constructor Create( Data: T_Settings_Data; OwnsObject: Boolean = True );
    destructor Destroy; override;
  end;

implementation

{ TSettings_v2_0 }

constructor TSettings_v2_0.Create( Data: T_Settings_Data; OwnsObject: Boolean );
begin
  inherited Create;
  FData := Data;
  FOwnsObject := OwnsObject;
end;

destructor TSettings_v2_0.Destroy;
begin
  if FOwnsObject
  then
    FData.Free;
  inherited;
end;

function TSettings_v2_0.GetBaud: Byte;
begin
  Result := FData.FBaud;
end;

procedure TSettings_v2_0.SetBaud( const Value: Byte );
begin
  FData.FBaud := Value;
end;

end.
ein kleiner Test zum Hin- und Herumschubsen der Daten
Delphi-Quellcode:
program dp_182543;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Settings in 'Settings.pas',
  Settings.v1_0 in 'Settings.v1_0.pas',
  Settings.v2_0 in 'Settings.v2_0.pas';

procedure Main;
var
  LOldSetting: T_Settings_XE4;
  LNewSetting: T_Settings_Data;
  LSettingOld, LSettingNew: TSettings;
begin
  // die try..finally Blöcke habe ich der Übersichtlichkeit halber weggelassen!
  LOldSetting.Baud := 24; // Wert im alten Format gespeichert
  LSettingOld := TSettings_V1_0.Create( LOldSetting ); // Wrapper drumherum

  LNewSetting := T_Settings_Data.Create; // neues Format
  LSettingNew := TSettings_v2_0.Create( LNewSetting ); // Wrapper drumherum

  LSettingNew.Assign( LSettingOld ); // einfach zuweisen

  Writeln( LNewSetting.Baud ); // und schon ist auch im neuen Format der Wert :o)
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

end.
In der Anwendung selber würde ich immer mit TSettings arbeiten, weil es dann egal ist, wie und woher die Einstellungen denn nun wirklich kommen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (31. Okt 2014 um 13:17 Uhr)
  Mit Zitat antworten Zitat