我想创建一个包含(ao)两个属性ObjectLinks和ObjectBacklinks的Tinterfacedobject。 Objectlinks包含对其他对象的接口引用,ObjectBacklinks包含这些链接的反向
两个属性都包含一个TWeakIntfDictionary = class(TDictionary) Backlinks属性在ObjectLinks.ValueNotify事件
中维护为了确保在原始对象被释放时从字典中删除接口引用,通知算法(与TFmxObject使用的相同)将被放置到位
怀疑我在创建对同一个interfacedobjects的这么多引用时遇到各种循环引用问题:(但我似乎无法摆脱这个问题。当从被破坏的对象调用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;
任何人都知道WeakReferences词典的现有实现? 有人建议如何解决这个问题?
答案 0 :(得分:0)
在以下代码中找到解决方案
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;