这个完全是你自己的代码问题.
//可以没有什么函数可以重载以便在接口属性移除时得到通知
SetIExplorerIntf就OK了
调试的方法太多了,推荐的方法,一个窗体,几个BUTTON,代码创建/设置/销毁 跟踪实现接口的类的析构函数.
要注意,如果你的实现接口类是简单类,没有其他额外的生命周期管理,那么没有什么问题,而如果是复杂类,比如TComponent,那么因为TComponent本身有生命周期管理,则需要在SetIExplorerIntf中通知你的实现类,以便在通过其他途径释放实现接口类的时候回调.
总得来讲,你需要系统的看一下 COM/DELPHI_INTERFACE 的生命管理这一块,如果你本身不是很明白的话,可以出错的地方太多,没办法弄的.
type IInterfaceClient_NoRefCount
procedure OnServerDestroy
//begin SetIExplorerIntf(nil)
end;
end;
type IInterfaceServer_NoRefCount
procedure RemoveNotifition(val : IInterfaceClient_NoRefCount);// FClientList.Remove(val);
procedure AddNotifition(val : IInterfaceClient_NoRefCount);//FClientList.Add(val);
end;
procedure TIntfClient.SetIExplorerIntf(NewVal : IExplorerIntf)
begin
if Assigned(FIExplorerIntf)
begin
//*********************
(FIExplorerIntf as IInterfaceServer_NoRefCount).RemoveNotifition(Self.FIExplorerIntf_CallBack as IInterfaceClient_NoRefCount);
//*********************
FIExplorerIntf := nil;
end;
FIExplorerIntf := NewVel;
(FIExplorerIntf as IInterfaceServer_NoRefCount).AddNotifition(Self.FIExplorerIntf_CallBack as IInterfaceClient_NoRefCount);
//使用IInterfaceServer_NoRefCount/IInterfaceClient_NoRefCount并不是太好的方法,一般推荐你使用VCL内部实现的模式,即直接使用一个简单类,这个实现你可以参考TImageList.OnChanged的实现原理
end;
Destruction TIntfClient.Desttructor()
begin
SetIExplorerIntf(nil);
...
inherited;
end;
这样接口客户端的实现就完成了,
Destruction TIntfServer.Destroy;
begin
for aInt:= FClientList.Count-1 downto 0 do
begin
(FClientList[aInt] as IInterfaceClient_NoRefCount).OnServerDestroy();
end;
end;
大致如此,一些席的地方还需要你自己设计,比如可能客户端(实现属性(类型为接口)的类)会有多个接口属性,参考到同一个实现对象,这时候仅仅是如此简单的注册可能就不够用了.
实现较为复杂是因为对于客户端/服务端都没有类型的限制,如果双方有内建机制比如TComponent,那么完全可以改造利用之。
不在多说了,如果你还有疑问,建议 阅读书籍/剖析VCl.