我想跳过Exception
类的一些属性的序列化,例如StackTrace
和RemoteStackTrace
(在WCF的上下文中需要这个用于自定义错误处理)。我怎样才能做到这一点?我很乐意在null
中将其值设置为GetObjectData()
,但我不能,因为底层字段是私有的(为什么他们总是将它们设为私有而不是保护?)
答案 0 :(得分:0)
幸运的是,Message
属性是虚拟的,其他我需要公共设置器,所以我只能禁用继承(de)序列化代码:
[Serializable]
public abstract class MyErrorBase : Exception
{
protected string reason;
public string TrackingID { get; set; }
public override string Message
{
get { return reason; }
}
public MyErrorBase() : this(null) { }
public MyErrorBase(string reason) : base(reason)
{
this.reason = reason;
// other init logic
}
protected MyErrorBase(SerializationInfo info, StreamingContext context)
{
HelpLink = info.GetString("HelpLink");
Source = info.GetString("Source");
TrackingID = info.GetString("TrackingID");
reason = info.GetString("Reason");
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Reason", reason);
info.AddValue("TrackingID", TrackingID);
info.AddValue("Source", Source);
info.AddValue("HelpLink", HelpLink);
}
}
令人惊讶的是,在重新抛出反序列化的实例时,禁用继承的逻辑对于CLR来说看起来非常好。
对于那些有兴趣为什么我需要这个。我的自定义WCF错误处理受到了这个令人敬畏的article的启发。因此,我的错误来自MyErrorBase
而不是琐碎的普通错误类,而我的操作合同看起来像这样:
[OperationContract]
[FaultContract(typeof(InvalidState))]
void Action();
InvalidState
继承自MyErrorBase
的地方。这样做很好,因为Exception
标有[Serializable]
- 这对DataContractSerializer
来说已经足够了。但是,您不希望通过服务调用公开任何类似堆栈跟踪的详细信息,是吗?
生成的信封(现在)如下所示:
<s:Fault>
<faultcode>s:InvalidState</faultcode>
<faultstring xml:lang="en-US">Cannot be processed in its current state.</faultstring>
<detail>
<InvalidState xmlns="http://schemas.datacontract.org/2004/07/MyNS" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
<Reason i:type="x:string" xmlns="">Cannot be processed in its current state.</Reason>
<TrackingID i:type="x:string" xmlns="">50547779-06d4-470d-ae75-a9feb3e08a99</TrackingID>
<Source i:type="x:string" xmlns="app1"/>
<HelpLink i:type="x:string" xmlns="">blabla</HelpLink>
<State i:type="x:int" xmlns="">2</State>
</InvalidState>
</detail>
</s:Fault>
最大的好处是非.NET消费者仍然很好(完全SOAP兼容性,我们不公开敏感数据),但服务的.NET使用者现在可以将错误提取为.NET异常并重新抛出它客户端(或处理故障通常的方式)。这比处理FaultException<T>
要好得多,因为您可以将故障组织为层次结构并享受catch块中的继承。由于类型(in)方差,FaultException<T>
在这里失败。