AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Ein Object in TObjectList<T> löschen mit Ereignis
Thema durchsuchen
Ansicht
Themen-Optionen

Ein Object in TObjectList<T> löschen mit Ereignis

Ein Thema von RWarnecke · begonnen am 1. Nov 2012 · letzter Beitrag vom 2. Nov 2012
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#1

Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 15:33
Delphi-Version: XE2
Hallo zusammen,

ich habe folgende Klassen erstellt :
Delphi-Quellcode:
type
  TModifyActionList = (lnNone, lnAdded, lnChange, lnDelete);

  TDegree = class
  private
    FOnChange : TNotifyEvent;
    FOnDelete : TNotifyEvent;
    FModifyAction : TModifyActionList;
    FID : Integer;
    FDegree : string;
    procedure SetID(const Value: Integer);
    procedure SetDegree(const Value: string);
  public
    property ID : Integer read FID write SetID;
    property Degree : string read FDegree write SetDegree;
    property ModifyAction : TModifyActionList read FModifyAction write FModifyAction;
    property OnChange : TNotifyEvent read FOnChange write FOnChange;
    property OnDelete : TNotifyEvent read FOnDelete write FOnDelete;
  end;

  TCustomObjectList<T: class> = class(TObjectList<T>)
  private
    FOnChange : TNotifyEvent;
    FOnDelete : TNotifyEvent;
    FModifyAction : TModifyActionList;
    FNewRecord : Boolean;
    procedure DeleteRecord(Klasse: T);
  protected
    function getItem(Index: Integer): T; virtual;
    procedure setItem(Index: Integer; Objekt: T); virtual;
    procedure Notify(const Item: T; Action: TCollectionNotification); override;
  public
    function Add(Objekt: T): Integer; virtual;
    function NewRecord(Objekt: T): Integer; virtual;
    function Remove(Objekt: T): Integer; virtual;
    function IndexOf(Objekt: T): Integer; virtual;
    procedure Insert(Index: Integer; Objekt: T); virtual;
    property Items[index: Integer]: T read getItem write setItem; default;
    property ModifyAction : TModifyActionList read FModifyAction write FModifyAction;
    property OnChange : TNotifyEvent read FOnChange write FOnChange;
    property OnDelete : TNotifyEvent read FOnDelete write FOnDelete;
  end;

{...}

{ TDegree }

procedure TDegree.SetDegree(const Value: string);
begin
  FDegree := Value;
  if (Assigned(FOnChange)) and (FModifyAction = lnChange) then
    FOnChange(Self);
end;

procedure TDegree.SetID(const Value: Integer);
begin
  FID := Value;
  if (Assigned(FOnChange)) and (FModifyAction = lnChange) then
    FOnChange(Self);
end;

{ TCustomObjectList<T> }

function TCustomObjectList<T>.Add(Objekt: T): Integer;
begin
  FNewRecord := False;
  Result := inherited Add(Objekt);
end;

procedure TCustomObjectList<T>.DeleteRecord(Klasse: T);
begin
  // To do something
end;

function TCustomObjectList<T>.getItem(Index: Integer): T;
begin
  Result := T(inherited Items[Index]);
end;

function TCustomObjectList<T>.IndexOf(Objekt: T): Integer;
begin
  Result := inherited IndexOf(Objekt);
end;

procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T);
begin
  inherited Insert(Index, Objekt);
end;

function TCustomObjectList<T>.NewRecord(Objekt: T): Integer;
begin
  FNewRecord := True;
  Result := inherited Add(Objekt);
end;

procedure TCustomObjectList<T>.Notify(const Item: T;
  Action: TCollectionNotification);
begin
  if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then
  begin
    FNewRecord := False;
    FOnChange(Self);
  end;
  if Action = cnRemoved then
  begin
    FOnDelete(Item);
  end;
  inherited Notify(Item, Action);
end;

function TCustomObjectList<T>.Remove(Objekt: T): Integer;
begin
  Result := inherited Remove(Objekt);
end;

procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T);
begin
  inherited Items[Index] := Objekt;
end;
Das funktioniert auch alles soweit ganz gut, bis auf den Teil mit FOnDelete. Warum bekomme ich jedesmal bei der Zeile FOnDelete(Item); eine AccessViolation ? Wie kann ich das beheben und was habe ich falsch gemacht ?
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

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

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 15:38
Prüf doch mal mit if Assigned( FOnDelete ) then ab, ob da was zugewiesen ist
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)
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#3

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 15:56
Habe ich das aus der OH für Assigned richtig verstanden, wenn ich folgende Zeilen Code chreibe :
Delphi-Quellcode:
  Degree := TDegree.Create;
  Degree.OnChange := TableEntryChange;
  Degree.OnDelete := TableEntryDelete;
  Degree.ID := FieldByName('ID').AsInteger;
  Degree.Degree := FieldByName('Degree').AsString;
  DegreeList.Add(Degree);
Dann gibt mir Assigned(FOnDelete) innerhalb der Klasse zurück, ob die Zeile Degree.OnDelete := TableEntryDelete; ausgeführt wurde oder nicht ? Wenn ja, dann ist es leider nicht der Fall. Assigned(FOnDelete) gibt immer False zurück. Warum ?

Der obere Code-Iteil wird in einer Schleife mehrmals wiederholt.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#4

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 16:03
Eigentlich sollte Assigned nach der Methodenzuweisung true zurückliefern. Bau doch mal temporär einen Setter ein, setz dort einen Haltepunkt und schau, ob der angesprungen wird. Ich sehe in dem Code keinen Grund, wieso das nicht so sein sollte.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#5

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 16:23
Bei den Klassen geht er in den Setter und weißt auch den richtigen Wert zu. Kann es vielleicht daran liegen, dass erst der Delete-Befehl ausgeführt wird und er dann ins Notify springt von TCustomObjectList<T: class> ?
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#6

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 16:32
Ich habe es gerade nicht im Kopf, aber möglicherweise ist das Item zwischen dem Delete und dem Notify bereits freigegeben, das würde die AV erklären.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#7

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 17:12
Ich habe es jetzt mal getestet. Wenn ich bei der Zeile if Action = cnRemoved then einen Breakpoint setze, steht der Count von der ObjectList um einen reduziert. Das heißt für mich, dass erst das Objekt gelöscht wird und dann Notify ausgeführt wird. Um das Ergebnis noch zu verifizieren, habe ich die Procedure Delete mit in meine abgeleitet Klasse übernommen. Es ist wirklich so, das erst die Delete Procedure ausgeführt wird und dann das Notify. Ich habe jetzt mal zusätzlich in der Delete-Procedure eine Abfrage auf Assigned(FOnDelete) gemacht. Auch hier wird ein False ausgegeben, wie kann das sein ?

Meine TCustomObjectList<T: class> sieht jetzt so aus :
Delphi-Quellcode:
  TCustomObjectList<T: class> = class(TObjectList<T>)
  private
    FOnChange : TNotifyEvent;
    FOnDelete : TNotifyEvent;
    FModifyAction : TModifyActionList;
    FNewRecord : Boolean;
    procedure SetOnDelete(const Value: TNotifyEvent);
    procedure SetOnChange(const Value: TNotifyEvent);
  protected
    function getItem(Index: Integer): T; virtual;
    procedure setItem(Index: Integer; Objekt: T); virtual;
    procedure Notify(const Item: T; Action: TCollectionNotification); override;
  public
    function Add(Objekt: T): Integer; virtual;
    procedure Delete(Index: Integer); virtual;
    function NewRecord(Objekt: T): Integer; virtual;
    function Remove(Objekt: T): Integer; virtual;
    function IndexOf(Objekt: T): Integer; virtual;
    procedure Insert(Index: Integer; Objekt: T); virtual;
    property Items[index: Integer]: T read getItem write setItem; default;
    property ModifyAction : TModifyActionList read FModifyAction write FModifyAction;
    property OnChange : TNotifyEvent read FOnChange write SetOnChange;
    property OnDelete : TNotifyEvent read FOnDelete write SetOnDelete;
  end;

{...}

{ TCustomObjectList<T> }

function TCustomObjectList<T>.Add(Objekt: T): Integer;
begin
  FNewRecord := False;
  Result := inherited Add(Objekt);
end;

procedure TCustomObjectList<T>.Delete(Index: Integer);
begin
  if Assigned(FOnDelete) then
    FOnDelete(Self);
  inherited Delete(Index);
end;

function TCustomObjectList<T>.getItem(Index: Integer): T;
begin
  Result := T(inherited Items[Index]);
end;

function TCustomObjectList<T>.IndexOf(Objekt: T): Integer;
begin
  Result := inherited IndexOf(Objekt);
end;

procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T);
begin
  inherited Insert(Index, Objekt);
end;

function TCustomObjectList<T>.NewRecord(Objekt: T): Integer;
begin
  FNewRecord := True;
  Result := inherited Add(Objekt);
end;

procedure TCustomObjectList<T>.Notify(const Item: T;
  Action: TCollectionNotification);
begin
  if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then
  begin
    FNewRecord := False;
    FOnChange(Self);
  end;
  inherited Notify(Item, Action);
end;

function TCustomObjectList<T>.Remove(Objekt: T): Integer;
begin
  Result := inherited Remove(Objekt);
end;

procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T);
begin
  inherited Items[Index] := Objekt;
end;

procedure TCustomObjectList<T>.SetOnChange(const Value: TNotifyEvent);
begin
  FOnChange := Value;
end;

procedure TCustomObjectList<T>.SetOnDelete(const Value: TNotifyEvent);
begin
  FOnDelete := Value;
end;
Bei if Assigned(FOnDelete) then steht der Count von TCustomObjectList<TDegree> noch auf der vollen Anzahl Objekte. Entweder verstehe ich hier etwas nicht oder es läuft irgendwas schief.

Edit:
Im Anhang meine DegreeList, nach dem Befüllen mit Daten. So wie ich das sehe, ist doch alles korrekt oder ?
Miniaturansicht angehängter Grafiken
clipboard01.jpg  
Rolf Warnecke
App4Mission

Geändert von RWarnecke ( 1. Nov 2012 um 17:30 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 17:42
Zitat:
eine AccessViolation
Und was für eine?

Was sagt denn der debugger, wenn du dir kurz vor dem aufruf den Wert dieser Variable anzeigen läßt?
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#9

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 17:55
Und was für eine?
---------------------------
Debugger Exception Notification
---------------------------
Project Project14.exe raised exception class $C0000005 with message 'access violation at 0x00000000: read of address 0x00000000'.
---------------------------
Break Continue Help
---------------------------
Was sagt denn der debugger, wenn du dir kurz vor dem aufruf den Wert dieser Variable anzeigen läßt?
Welchen Wert meinst Du ?
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Ein Object in TObjectList<T> löschen mit Ereignis

  Alt 1. Nov 2012, 18:17
Delphi-Quellcode:
  if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then // hier hast'e geprüft
  begin
    FNewRecord := False;
    FOnChange(Self);
  end;
  if Action = cnRemoved then // hier nicht
  begin
    FOnDelete(Item); // hier haltepunkt hin und schauen was in FOnDelete steht, *1
  end;
1) aber vemutlich wirklich ein "nil".
Jedenfalls sieht die Exception danach aus, da dort zur Adresse 0 (nil) gesprungen wurde und weil dort kein ausführbarer Code steht, knallt es.
(aber natürlich kann es auch noch innerhalb einer verlinkten Methode knallen, aber da sollte der Debugger ebenfalls hilfreich sein)

Der schon genannte Trick mit dem Setter würde zmindestens zeigen, ob, wann und wo dieses Property verändert wird.
$2B or not $2B

Geändert von himitsu ( 1. Nov 2012 um 18:20 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz