【问题标题】:Overriding System.Exception serialization覆盖 System.Exception 序列化
【发布时间】:2012-02-05 07:59:05
【问题描述】:

我想跳过Exception 类的某些属性的序列化,例如StackTraceRemoteStackTrace(在WCF 上下文中进行自定义错误处理需要这个)。我怎样才能做到这一点?我很乐意在GetObjectData() 中将它们的值设置为null,但我不能,因为底层字段是私有的(为什么他们总是将它们设为私有而不是受保护?)

【问题讨论】:

  • 你不能。我也无法提供替代方案,因为您没有努力描述为什么您会考虑如此严重地破坏 Exception 类。这些字段是私有的,这是有充分理由的。
  • 为什么会这样? StackTrace 和 RemoteStackTrace 对于 Exception 序列化都不是至关重要的。我只是不想序列化敏感数据(安全问题)。
  • 你试过用故障代替吗?
  • Marc,我确实使用了类型错误,但它们有一些限制,请参阅我的回答。

标签: .net exception serialization


【解决方案1】:

幸运的是,Message 属性是虚拟的,而我需要的其他属性具有公共设置器,因此我可以禁用继承的(反)序列化代码:

[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&lt;T&gt; 要好得多,因为您可以将故障组织为层次结构并享受捕获块中的继承。 FaultException&lt;T&gt; 在这里失败,因为类型(in)方差。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2014-03-18
    • 1970-01-01
    • 2019-05-23
    • 2013-10-02
    • 1970-01-01
    • 2021-03-26
    相关资源
    最近更新 更多