我有一个使用DCOM技术的界面。
接口中定义的所有方法都具有safecall
指令。
但是,在客户端,我想在TObject中反映这个对象,以避免每次我需要读取它时都使用接口传输。
例如
IMyInterface = interface(IDispatch);
procedure Set_fA(const Value: WideString); safecall;
function Get_fA: WideString; safecall;
end;
此接口由TAutoIntfObject
实现,在这种情况下,实现保持safecall
指令
TMyAuto = class(TAutoIntfObject, IMyInterface)
private
fA : WideString;
public
procedure Set_fA(const Value: WideString); safecall;
function Get_fA: WideString; safecall;
end;
但现在,使用TObject如果我删除safecall:
TMyObject = class(TObject, IMyInterface)
private
fA : WideString;
public
procedure Set_fA(const Value: WideString); //??
function Get_fA: WideString; //??
procedure CopyFromServer(Original: OleVariant);
end;
编译器生成以下错误: “Set_fA的声明与接口IMyObject中的声明不同”
我通常可以使用TObject和safecall,如果我保持这种方式会有任何麻烦吗? 在任何情况下,safecall都会产生差异而不是cdecl吗?
我之所以这样做,是因为每次我需要阅读一些TMyAuto
实例属性时,我都希望避免转移到服务器。
答案 0 :(得分:2)
如果数据的规范值在服务器上,但每次要访问该值时都不必访问服务器,则可以在本地缓存它。它看起来像这样:
TMyObject = class(TObject)
private
fServerInterface: IMyInterface;
fDataLoaded: boolean;
//cached data
fA : WideString;
procedure LoadAllData;
public
procedure Set_fA(const Value: WideString);
function Get_fA: WideString;
end;
function TMyObject.Get_fA: WideString;
begin
if not fDataLoaded then
LoadAllData;
result := fA;
end;
procedure TMyObject.Set_fA(const Value: WideString);
begin
fServerInterface.Set_fA(value);
fA := value;
end;
procedure TMyObject.LoadAllData;
begin
fA := fServerInterface.Get_fA;
fDataLoaded := true;
end;
然后您拥有数据的本地副本,并且您不必每次都从服务器获取它。
缺点是,您的数据已缓存。如果其他人同时访问服务器,并且保持缓存与主数据存储同步,则缓存可能变为陈旧(过时),这两者之一被认为是真正困难的两个之一计算机科学中的问题。
如果您不确定在缓存数据时不会更改数据,则可以通过两种方式对其进行管理。首先,设置一个系统,对主数据存储所做的任何更改都会发送给每个拥有缓存副本的人,以便他们可以更新缓存。这可能是非常复杂和涉及的,如果你有一个具有一定规模和复杂性的系统,它真的是值得的。
或者,第二,不要缓存可能会改变的数据。只是将开销作为开展业务成本的一部分。
您选择哪种解决方案取决于您。不过,请确保在决定之前对事情进行分析。
答案 1 :(得分:2)
继续,将safecall
放回你的方法上。界面需要它。该接口还要求您实现IDispatch
引入的其余方法,因为TObject
本身并未实现它们。
Safecall和cdecl是完全不同的调用约定;他们永远不可互换。它们在清理堆栈方面有所不同,它们在调用者和接收者之间传输错误的方式不同。接口指定了一个,因此在实现时不会选择不同的东西。