【问题标题】:How to create TDictionary containing weak references to interfaces in delphi如何在delphi中创建包含对接口的弱引用的TDictionary
【发布时间】:2012-10-24 14:29:46
【问题描述】:

我想创建一个包含 (ao) 两个属性 ObjectLinks 和 ObjectBacklinks 的 Tinterfacedobject。 Objectlinks 包含对其他对象的接口引用,ObjectBacklinks 包含这些链接的反向

这两个属性都包含一个 TWeakIntfDictionary = class(TDictionary) Backlinks 属性在 ObjectLinks.ValueNotify 事件中维护

为了确保在释放原始对象时从字典中删除接口引用,使用通知算法(与 TFmxObject 使用相同)

怀疑我在创建这么多对相同接口对象的引用时遇到了各种循环引用问题:(但我似乎无法摆脱这个问题。当从被销毁的对象调用 FreeNotification 时,一切都很好,直到它从 FreeNOtification 返回。此时再次调用对象的 .Destroy :-(

 {1 Dictionary of interfaces (using weak references) using Free notification }
  TWeakIntfDictionary = class(TDictionary<int64, IInterface>, IFreeNotificationMonitor)
  protected
    procedure ValueNotify(const Value: IInterface; Action: TCollectionNotification); override;
  public
    procedure FreeNotification(aObject: TObject);
  end;

  implementation

  procedure TWeakIntfDictionary.FreeNotification(aObject: TObject);
  var
    lObj: TPair<int64, IInterface>;
  begin
    //Object is going to be destroyed, remove it from dictionary
    for lObj in Self do
    begin
      if (lObj.Value as TObject).Equals(aObject) then
      begin
        Remove(lObj.Key);
        Break;
      end;
    end;
  end;

  procedure TWeakIntfDictionary.ValueNotify(const Value: IInterface; Action: TCollectionNotification);
  var
    lDestrIntf: IFreeNotificationBehavior;
  begin
      // When a TObject is added to the dictionary, it must support IDestroyNotification
      // This dictionary is than added to the notificationlist of the TObject
    if Supports(Value, IFreeNotificationBehavior, lDestrIntf) then
      case Action of
        cnAdded:      begin
                        lDestrIntf.AddFreeNotify(Self);
                        lDestrIntf._Release;
                      end;
        cnRemoved,
        cnExtracted:  begin
                        lDestrIntf.RemoveFreeNotify(Self);
                      end;
      end
    else
      raise EWeakInftDictionaryException.Create('Object added to TWeakIntfDictionary does not support IFreeNotificationBehavior');

    inherited;

  end;

有人知道弱引用字典的现有实现吗? 任何人有任何建议如何解决这个问题?

【问题讨论】:

  • 如果这些是唯一的引用,则不需要弱引用。当 A 引用 B 并且 B 引用 A 时,您需要弱引用。您所描述的是一个充满 A 和 B 引用的容器。那里没有循环。
  • 你之前没有说过这些。我看不到任何证据表明该列表是双重链接的。我看不出这个问题有任何循环性。
  • 第二句:“Objectlinks 包含对其他对象的接口引用,ObjectBacklinks 包含那些链接的反向”
  • 这不是循环的。你需要 A 持有对 B 的引用,B 持有对 A 的引用。你有 C 持有对 A 和 B 的引用。或者 A 和 B 持有对 C 的引用?
  • 无论如何,如果你有这个,让容器保持指针而不是接口类型。

标签: delphi delphi-xe2


【解决方案1】:

在下面的代码中找到了解决方案

procedure TWeakIntfDictionary.FreeNotification(aObject: TObject);
var
  ...
begin
  //Object is going to be destroyed, remove it from dictionary
  lSavedEvent := FDict.OnValueNotify;
  FDict.OnValueNotify := nil;
  lRemoveList := TList<TKey>.Create;
  try
    for lPair in FDict do
    begin
      pointer(lIntf) := lPair.Value;
      if (lIntf as TObject) = aObject then
        lRemoveList.Add(lPair.Key);
    end;
    pointer(lIntf):=nil; // avoid _release for the last item

    for lKey in lRemoveList do
      FDict.Remove(lKey);

  finally
    FDict.OnValueNotify := lSavedEvent;
    lRemoveList.Free;
  end;
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    相关资源
    最近更新 更多