2

NamedPipe を介して、タイプ Exception (またはそのサブクラスの 1 つ) のオブジェクトを渡そうとしています。

サービス契約:

[ServiceContract]
public interface IWCFCallback
{
    [OperationContract]
    void sendException(Exception e);
}

次のように使用すると正常に動作します。

_pipeproxy.sendException(new Exception("bla bla 99"));

しかし、サブクラスを渡すとすぐに:

_pipeproxy.sendException(new ArgumentException("fridgemaster 3000"));

逆シリアル化に失敗したという例外が発生します。

KnownTypes 属性については既に読みましたが、自分で実装していないクラスに使用する方法がわかりません。

誰かがここでヒントをくれますか?

4

2 に答える 2

2

WCF の「ベスト プラクティス」の 1 つは、例外をシリアル化しないことです。
ServiceHost が例外をスローしている場合は、FaultException を使用することを想定しています。
例外を安全に転送できない理由の 1 つは、Exception 自体はシリアル化可能ですが、そこから派生させることができ、カスタム派生例外がシリアル化できることを誰が保証するかということです。

回避策として、例外スタックを文字列として、型を列挙型としてデータ コントラクト オブジェクトを渡すことができます。

于 2013-08-09T08:59:47.700 に答える
1

これはベスト プラクティスに従っていない可能性がありますが、次のような例外を表す DataContract を作成できます。

/// <summary>
/// Represents errors that occur during application execution.
/// </summary>
[DataContract]
public class ExceptionInfo
{
    /// <summary>
    /// Gets the type of the exception.
    /// </summary>
    [DataMember]
    public string ExceptionType
    {
        get;
        set;
    }

    /// <summary>
    /// Gets a message that describes the current exception.
    /// </summary>
    /// <returns>
    /// The error message that explains the reason for the exception, or an empty string("").
    /// </returns>
    [DataMember]
    public string Message
    {
        get;
        set;
    }

    /// <summary>
    /// Gets the <see cref="T:System.Exception"/> instance that caused the current exception.
    /// </summary>
    /// <returns>
    /// An instance of Exception that describes the error that caused the current exception. The InnerException property returns the same value as was passed into the constructor, or a null reference (Nothing in Visual Basic) if the inner exception value was not supplied to the constructor. This property is read-only.
    /// </returns>
    [DataMember]
    public ExceptionInfo InnerException
    {
        get;
        set;
    }

    /// <summary>
    /// Gets a string representation of the immediate frames on the call stack.
    /// </summary>
    /// <returns>
    /// A string that describes the immediate frames of the call stack.
    /// </returns>
    [DataMember]
    public string StackTrace
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a link to the help file associated with this exception.
    /// </summary>
    /// <returns>
    /// The Uniform Resource Name (URN) or Uniform Resource Locator (URL).
    /// </returns>
    [DataMember]
    public string HelpLink
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets the name of the application or the object that causes the error.
    /// </summary>
    [DataMember]
    public string Source
    {
        get;
        set;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ExceptionInfo"/> class.
    /// </summary>
    /// <param name="exception">The exception.</param>
    /// <exception cref="ArgumentNullException">exception</exception>
    public ExceptionInfo(Exception exception)
    {
        if(exception == null)
            throw new ArgumentNullException("exception");

        ExceptionType = exception.GetType().FullName;
        HelpLink = exception.HelpLink;
        Message = exception.Message;
        Source = exception.Source;
        StackTrace = exception.StackTrace;

        if(exception.InnerException != null)
        {
            InnerException = new ExceptionInfo(exception.InnerException);
        }
    }
}

サービス契約:

[ServiceContract]
public interface IWCFCallback
{
    [OperationContract]
    void sendException(ExceptionInfo e);
}

使用法:

try
{
    // .....
}
catch (Exception ex)
{
    var info = new ExceptionInfo(ex);

    // do something....
}
于 2013-08-09T09:21:25.980 に答える