首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 行為擴展深度解析:從參數攔截到訊息檢查器的完整實作指南

     編輯:關於.NET

WCF 擁有極具彈性的擴展架構,其中行為擴展是最常見且強大的切入點。本文系統梳理伺服器端與客戶端擴展點、四種行為類型、配置與屬性兩種啟用方式,並提供完整程式碼範例。

核心擴展點介面

層面運行階段擴展介面用途
伺服器端DispatchRuntimeIParameterInspector參數檢查(呼叫前/後)
DispatchRuntimeIDispatchMessageInspector訊息檢查(接收請求/發送回覆)
DispatchOperationIOperationInvoker自訂操作調用邏輯
客戶端ClientRuntimeIParameterInspector參數檢查(共用介面)
ClientRuntimeIClientMessageInspector訊息檢查(發送請求/接收回覆)

所有介面定義於 System.ServiceModel.Dispatcher 命名空間。IParameterInspector 可同時用於雙端。

參數攔截器實作

public class CalculatorParameterInspector : IParameterInspector {
    public object BeforeCall(string operationName, object[] inputs) {
        int x = (int)inputs[0], y = (int)inputs[1];
        if (x < 0 || y < 0)
            throw new FaultException("The number can not be less than zero.");
        return null; // 相關狀態傳給 AfterCall
    }

    public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) {
        // 可記錄回傳值、效能監控等
    }
}

訊息攔截器實作

public class PrintMessageInterceptor : IDispatchMessageInspector {
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) {
        var buffer = request.CreateBufferedCopy(int.MaxValue);
        request = buffer.CreateMessage();
        Console.WriteLine("After Receive Request:");
        foreach (var header in request.Headers) Console.WriteLine(header);
        Console.WriteLine(new string('*', 20));
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState) {
        var buffer = reply.CreateBufferedCopy(int.MaxValue);
        reply = buffer.CreateMessage();
        Console.WriteLine("Before Send Reply:");
        foreach (var header in reply.Headers) Console.WriteLine(header);
        Console.WriteLine(new string('*', 20));
    }
}

注意:IDispatchMessageInspector(伺服端)方法順序為 AfterReceiveRequest → BeforeSendReply;IClientMessageInspector(客戶端)則相反:BeforeSendRequest → AfterReceiveReply。

四種行為類型與作用範圍

行為類型介面服務端點合約操作
服務行為IServiceBehavior✓✓✓✓
端點行為IEndpointBehavior✓✓✓
合約行為IContractBehavior✓✓
操作行為IOperationBehavior✓

三種啟用方式比較

方式服務行為端點行為合約行為操作行為
自訂屬性✓✗✓✓
配置檔✓✓✗✗
ServiceDescription 程式碼✓✓✓✓

方式一:自訂屬性啟用

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class MyServiceBehavior : Attribute, IServiceBehavior {
    // 實作 IServiceBehavior 三個方法...
}

[MyServiceBehavior]
public interface IService { ... }

方式二:配置檔啟用(需 BehaviorExtensionElement)

public class MyBehaviorExtensionElement : BehaviorExtensionElement {
    public override Type BehaviorType => typeof(MyServiceBehavior);
    protected override object CreateBehavior() => new MyServiceBehavior();

    [ConfigurationProperty("providerName", IsRequired = true)]
    public string ProviderName {
        get => (string)this["providerName"];
        set => this["providerName"] = value;
    }
}

配置檔:

<system.serviceModel>
  <services>
    <service name="Demo.Calculator">
      <endpoint behaviorConfiguration="messageInspectorBehavior" ... />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="messageInspectorBehavior">
        <myBehaviorExtensionElement providerName="Test" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <extensions>
    <behaviorExtensions>
      <add name="myBehaviorExtensionElement"
           type="Demo.MyBehaviorExtensionElement, Demo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
</system.serviceModel>

關鍵細節:type 必須為完整型別名稱(含命名空間、版本、文化特性、公開金鑰),逗號後必須保留一空格,否則反射載入失敗。

行為中掛載攔截器

參數檢查 → IOperationBehavior

public class CalculatorParameterValidation : Attribute, IOperationBehavior {
    public void ApplyClientBehavior(OperationDescription desc, ClientOperation op) {
        op.ParameterInspectors.Add(new CalculatorParameterInspector());
    }
    public void ApplyDispatchBehavior(OperationDescription desc, DispatchOperation op) {
        op.ParameterInspectors.Add(new CalculatorParameterInspector());
    }
    // AddBindingParameters, Validate 留空
}

進階:合併介面實作

public class CalculatorParameterValidation : Attribute, IParameterInspector, IOperationBehavior {
    // 實作 IParameterInspector 方法...
    public void ApplyClientBehavior(OperationDescription desc, ClientOperation op) {
        op.ParameterInspectors.Add(this); // this 即為參數檢查器
    }
    public void ApplyDispatchBehavior(OperationDescription desc, DispatchOperation op) {
        op.ParameterInspectors.Add(this);
    }
}

操作調用器 → IOperationBehavior + DispatchOperation.Invoker

public class MyOperationInvokerBehavior : Attribute, IOperationBehavior {
    public void ApplyDispatchBehavior(OperationDescription desc, DispatchOperation op) {
        op.Invoker = new MyOperationInvoker(op.Invoker); // 裝飾模式包裝原調用器
    }
}

訊息檢查器 → IEndpointBehavior / IServiceBehavior

public class PrintMessageInspectorBehavior : IDispatchMessageInspector, IEndpointBehavior {
    // 實作 IDispatchMessageInspector...

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
        clientRuntime.MessageInspectors.Add(this);
    }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher dispatcher) {
        dispatcher.DispatchRuntime.MessageInspectors.Add(this);
    }
}

若實作 IServiceBehavior,需遍歷 ServiceHostBase.ChannelDispatchers:

public void ApplyDispatchBehavior(ServiceDescription desc, ServiceHostBase host) {
    foreach (var chDisp in host.ChannelDispatchers)
        foreach (var epDisp in chDisp.Endpoints)
            epDisp.DispatchRuntime.MessageInspectors.Add(this);
}

總結

  • 行為擴展是 WCF AOP 風格切面的核心實現機制
  • 選擇正確的行為類型(服務/端點/合約/操作)對應作用範圍
  • 屬性啟用適合編譯期靜態綁定,配置檔啟用適合部署期動態調整
  • 攔截器(Inspector/Invoker)與行為類別分離符合單一職責,亦可合併簡化
  • 配置檔 type 字串格式嚴格,逗號後空格不可省略
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved