WCF Client Extensibility: IParemeterInspector.AfterCall and Exception Handling

For my WCF client, I would like to be able to do some pre and post for every operation of a given endpoint.

  • Pre work involves using the operation name and input arguments .
  • Post job would like to use (again) operation nameand the original input arguments , as well as the output / return value or any exception that occurred.

Given this, IParameterInspector(with his BeforeCalland AfterCall) gives me almost everything I need. The problem is that

  • in case of an exception, AfterCallit is not called (see here ).

To help with this problem, I can add IClientMessageInspector, as it AfterReceiveReplyis called in the face of an exception. It gives me the opportunity

  • determine if an exception occurred (error).
  • do post work in the face of exceptions

Question:

  • Is there a way to IClientMessageInspector.AfterReceiveReplyget (or create an equivalent) an exception that represents what will eventually be passed to the caller. And if so, is there a way to mark the exception as handled in such a way that callers do not receive the exception?
  • , , ?
+4
1

, . IClientMessageInspector.AfterReceiveReply "" IClientMessageFormatter.DeserializeReply.

.

:

public sealed class FakeMessage : Message
{
    #region Fields

    private MessageProperties properties;
    private MessageHeaders headers;

    #endregion

    #region Constructors

    public FakeMessage(MessageVersion version, string action)
    {
        this.headers = new MessageHeaders(version);
        this.headers.Action = action;
    }

    #endregion

    #region Message Members

    public override MessageHeaders Headers
    {
        get { return headers; }
    }

    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        throw new NotSupportedException();
    }

    public override MessageProperties Properties
    {
        get
        {
            if (this.properties == null)
            { properties = new MessageProperties(); }

            return properties;
        }
    }

    public override MessageVersion Version
    {
        get { return headers.MessageVersion; }
    }

    #endregion
}

:

public sealed class FakeMessageFormatter : IClientMessageFormatter
{
    #region Fields

    private IClientMessageFormatter baseFormatter;
    private object defaultReturnValue;

    #endregion

    #region Construcotrs

    public FakeMessageFormatter(IClientMessageFormatter baseFormatter, Type returnType)
    {
        this.baseFormatter = baseFormatter;

        if (returnType.IsValueType && returnType != typeof(void))
        { this.defaultReturnValue = Activator.CreateInstance(returnType); }
    }

    #endregion

    #region IClientMessageFormatter Members

    public object DeserializeReply(Message message, object[] parameters)
    {
        if (message is FakeMessage)
        { return defaultReturnValue; }

        return baseFormatter.DeserializeReply(message, parameters);
    }

    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
    {
        return baseFormatter.SerializeRequest(messageVersion, parameters);
    }

    #endregion
}

, , :

public sealed class FakeMessageInspector : IClientMessageInspector
{
    #region IClientMessageInspector Members

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        if (reply.IsFault)
        { reply = new FakeMessage(reply.Version, (string)correlationState); }
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        return request.Headers.Action + "Response";
    }

    #endregion
}
0

All Articles