当我在TDatasetProvider.OnUpdateError事件中重新抛出一个EUpdateError异常时,它在catch块中没有被识别为EUpdateError异常。它只被识别为基本Excption。
try
...
//calls the TDatasetPorvider.OnUpdateError event.
myClientDataSet.ApplyUpdates(0);
...
except
on ex: EUpdateError do
begin
//never goes here
//Evaluate ex.ErrorCode
end;
on ex: Exception do
begin
//always goes here
//the expression (ex is EUpdateError) returns false;
end;
end;下面是相应的.OnUpdateError实现:
procedure MyDataModule.MyDatasetProviderOnUpdateError(..;E: EUpdateError;...);
beign
//Here, the expression (E is EUpdateException) returns true;
raise E;
end;异常被重新抛出,但是看起来EUpdateError被转换成了一个简单的基本Exection.
有人知道为什么类类型迷失了方向吗?
我需要该类型,以便检查.ErrorCode,了解哪里出了问题,并准备适当的用户消息。
发布于 2010-05-26 21:25:21
不幸的是,“旧式”DataSnap服务器异常是作为纯文本(E.Message)编组到客户端的,因此异常类名和实例数据会在此过程中丢失。请参见SConnect单元、TDataBlockInterpreter.InterpretData方法( except块)。
编辑:这里是一个非常简单的例子,给你一个想法(根本没有测试):
// new methods
function TDataBlockInterpreter.ReadException(const Data: IDataBlock): Exception;
var
Flags: TVarFlags;
AClassName, AMessage, AContext: string;
ErrorCode, PreviousError: Integer;
OriginalException: Exception;
begin
AClassName := ReadVariant(Flags, Data);
AMessage := ReadVariant(Flags, Data);
if AClassName = 'EUpdateError' then
begin
AContext := ReadVariant(Flags, Data);
ErrorCode := ReadVariant(Flags, Data);
PreviousError := ReadVariant(Flags, Data);
OriginalException := ReadException(Data);
Result := EUpdateError.Create(AMessage, AContext, ErrorCode, PreviousError, OriginalException);
end
// else if AClassName = ... then ...
else
Result := Exception.Create(AMessage);
end;
procedure TDataBlockInterpreter.WriteException(E: Exception; const Data: IDataBlock);
begin
WriteVariant(E.ClassName, Data);
WriteVariant(E.Message, Data);
if E is EUpdateError then
begin
WriteVariant(EUpdateError(E).Context, Data);
WriteVariant(EUpdateError(E).ErrorCode, Data);
WriteVariant(EUpdateError(E).PreviousError, Data);
WriteException(EUpdateError(E).OriginalException, Data);
end;
end;
// modified methods
procedure TDataBlockInterpreter.DoException(const Data: IDataBlock);
begin
raise ReadException(Data);
end;
procedure TDataBlockInterpreter.InterpretData(const Data: IDataBlock);
var
Action: Integer;
begin
Action := Data.Signature;
if (Action and asMask) = asError then DoException(Data);
try
case (Action and asMask) of
asInvoke: DoInvoke(Data);
asGetID: DoGetIDsOfNames(Data);
asCreateObject: DoCreateObject(Data);
asFreeObject: DoFreeObject(Data);
asGetServers: DoGetServerList(Data);
asGetAppServers: DoGetAppServerList(Data);
else
if not DoCustomAction(Action and asMask, Data) then
raise EInterpreterError.CreateResFmt(@SInvalidAction, [Action and asMask]);
end;
except
on E: Exception do
begin
Data.Clear;
Data.Signature := ResultSig or asError;
WriteException(E, Data);
FSendDataBlock.Send(Data, False);
end;
end;
end;https://stackoverflow.com/questions/2911921
复制相似问题